过滤搜索结果
编辑过滤搜索结果编辑
您可以使用两种方法来过滤搜索结果
后置过滤器编辑
当您使用 post_filter
参数来过滤搜索结果时,搜索命中将在计算聚合后进行过滤。后置过滤器不会影响聚合结果。
例如,您正在销售具有以下属性的衬衫
response = client.indices.create( index: 'shirts', body: { mappings: { properties: { brand: { type: 'keyword' }, color: { type: 'keyword' }, model: { type: 'keyword' } } } } ) puts response response = client.index( index: 'shirts', id: 1, refresh: true, body: { brand: 'gucci', color: 'red', model: 'slim' } ) puts response
PUT /shirts { "mappings": { "properties": { "brand": { "type": "keyword"}, "color": { "type": "keyword"}, "model": { "type": "keyword"} } } } PUT /shirts/_doc/1?refresh { "brand": "gucci", "color": "red", "model": "slim" }
假设用户指定了两个过滤器
color:red
和 brand:gucci
。您只想在搜索结果中向他们展示 Gucci 制造的红色衬衫。通常,您会使用 bool
查询
response = client.search( index: 'shirts', body: { query: { bool: { filter: [ { term: { color: 'red' } }, { term: { brand: 'gucci' } } ] } } } ) puts response
GET /shirts/_search { "query": { "bool": { "filter": [ { "term": { "color": "red" }}, { "term": { "brand": "gucci" }} ] } } }
但是,您还想使用分面导航来显示用户可以点击的其他选项列表。也许您有一个 model
字段,允许用户将搜索结果限制为红色的 Gucci t-shirts
或 dress-shirts
。
这可以通过 terms
聚合
response = client.search( index: 'shirts', body: { query: { bool: { filter: [ { term: { color: 'red' } }, { term: { brand: 'gucci' } } ] } }, aggregations: { models: { terms: { field: 'model' } } } } ) puts response
GET /shirts/_search { "query": { "bool": { "filter": [ { "term": { "color": "red" }}, { "term": { "brand": "gucci" }} ] } }, "aggs": { "models": { "terms": { "field": "model" } } } }
但也许您还想告诉用户有多少 Gucci 衬衫有 其他颜色。如果您只是在 color
字段上添加一个 terms
聚合,您只会得到颜色 red
,因为您的查询只返回 Gucci 制造的红色衬衫。
相反,您希望在聚合期间包含所有颜色的衬衫,然后仅将 colors
过滤器应用于搜索结果。这就是 post_filter
的目的
response = client.search( index: 'shirts', body: { query: { bool: { filter: { term: { brand: 'gucci' } } } }, aggregations: { colors: { terms: { field: 'color' } }, color_red: { filter: { term: { color: 'red' } }, aggregations: { models: { terms: { field: 'model' } } } } }, post_filter: { term: { color: 'red' } } } ) puts response
GET /shirts/_search { "query": { "bool": { "filter": { "term": { "brand": "gucci" } } } }, "aggs": { "colors": { "terms": { "field": "color" } }, "color_red": { "filter": { "term": { "color": "red" } }, "aggs": { "models": { "terms": { "field": "model" } } } } }, "post_filter": { "term": { "color": "red" } } }
主查询现在找到所有 Gucci 制造的衬衫,无论颜色如何。 |
|
|
|
|
|
最后, |
重新评分过滤后的搜索结果编辑
重新评分可以通过使用辅助(通常更昂贵)算法重新排序由 query
和 post_filter
阶段返回的顶部(例如 100-500)文档来帮助提高精度,而不是将昂贵的算法应用于索引中的所有文档。
rescore
请求在每个分片上执行,然后将其结果返回到处理整体搜索请求的节点。
目前,重新评分 API 只有一个实现:查询重新评分器,它使用查询来调整评分。将来,可能会提供其他重新评分器,例如成对重新评分器。
如果在 rescore
查询中提供了显式 sort
(除了按降序排列的 _score
),则会抛出错误。
当向用户公开分页时,您不应该更改 window_size
,因为您在浏览每个页面时(通过传递不同的 from
值)会更改它,因为这可能会改变热门结果,导致结果在用户浏览页面时令人困惑地发生变化。
查询重新评分器编辑
查询重新评分器仅对由 query
和 post_filter
阶段返回的 Top-K 结果执行第二个查询。可以在每个分片上检查的文档数量可以通过 window_size
参数控制,该参数默认为 10。
默认情况下,来自原始查询和重新评分查询的得分将线性组合以生成每个文档的最终 _score
。原始查询和重新评分查询的相对重要性可以通过 query_weight
和 rescore_query_weight
分别控制。两者都默认为 1
。
例如
response = client.search( body: { query: { match: { message: { operator: 'or', query: 'the quick brown' } } }, rescore: { window_size: 50, query: { rescore_query: { match_phrase: { message: { query: 'the quick brown', slop: 2 } } }, query_weight: 0.7, rescore_query_weight: 1.2 } } } ) puts response
POST /_search { "query" : { "match" : { "message" : { "operator" : "or", "query" : "the quick brown" } } }, "rescore" : { "window_size" : 50, "query" : { "rescore_query" : { "match_phrase" : { "message" : { "query" : "the quick brown", "slop" : 2 } } }, "query_weight" : 0.7, "rescore_query_weight" : 1.2 } } }
可以通过 score_mode
控制得分组合的方式
得分模式 | 描述 |
---|---|
|
添加原始得分和重新评分查询得分。默认值。 |
|
将原始得分乘以重新评分查询得分。适用于 |
|
对原始得分和重新评分查询得分求平均值。 |
|
取原始得分和重新评分查询得分的最大值。 |
|
取原始得分和重新评分查询得分的最小值。 |
多个重新评分编辑
也可以按顺序执行多个重新评分
response = client.search( body: { query: { match: { message: { operator: 'or', query: 'the quick brown' } } }, rescore: [ { window_size: 100, query: { rescore_query: { match_phrase: { message: { query: 'the quick brown', slop: 2 } } }, query_weight: 0.7, rescore_query_weight: 1.2 } }, { window_size: 10, query: { score_mode: 'multiply', rescore_query: { function_score: { script_score: { script: { source: 'Math.log10(doc.count.value + 2)' } } } } } } ] } ) puts response
POST /_search { "query" : { "match" : { "message" : { "operator" : "or", "query" : "the quick brown" } } }, "rescore" : [ { "window_size" : 100, "query" : { "rescore_query" : { "match_phrase" : { "message" : { "query" : "the quick brown", "slop" : 2 } } }, "query_weight" : 0.7, "rescore_query_weight" : 1.2 } }, { "window_size" : 10, "query" : { "score_mode": "multiply", "rescore_query" : { "function_score" : { "script_score": { "script": { "source": "Math.log10(doc.count.value + 2)" } } } } } } ] }
第一个获取查询的结果,然后第二个获取第一个的结果,等等。第二个重新评分将“看到”由第一个重新评分完成的排序,因此可以在第一个重新评分中使用一个大的窗口将文档拉入第二个重新评分的较小窗口中。