Filter search result
Post filter
数据初始化:
PUT /shirts { "mappings": { "properties": { "brand": { "type": "keyword"}, "color": { "type": "keyword"}, "model": { "type": "keyword"} } } } PUT /shirts/_doc/1?refresh { "brand": "gucci", "color": "red", "model": "slim" } PUT /shirts/_doc/2?refresh { "brand": "gucci", "color": "black", "model": "slim" } PUT /shirts/_doc/3?refresh { "brand": "gucci", "color": "green", "model": "slim" } PUT /shirts/_doc/4?refresh { "brand": "gucci", "color": "white", "model": "hat" } PUT /shirts/_doc/5?refresh { "brand": "gucci", "color": "red", "model": "hat" }
我们创建了一个索引shirts,映射字段:brand品牌、color颜色、类型(衬衫、帽子),并初始化5条数据(3个衬衫红、绿、黑;2个帽子红、白)。
查询:
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" } } }
在上面的查询中:
1、我们查询 brand=gucci 的商品。并使用postfilter对查询结果进行过滤,只返回颜色为red的商品,结果我们得到了2件商品:1件红色的衬衫,1顶红色的帽子。
2、同时,我们定义了2个聚合:
colors:返回所有颜色商品的数量。
color_red:根据model分组,返回每种分组下红色商品的数量。
返回结果:
{ "took" : 6, "timed_out" : false, "_shards" : { "total" : 1, "successful" : 1, "skipped" : 0, "failed" : 0 }, "hits" : { "total" : { "value" : 2, "relation" : "eq" }, "max_score" : 0.0, "hits" : [ { "_index" : "shirts", "_type" : "_doc", "_id" : "2", "_score" : 0.0, "_source" : { "brand" : "gucci", "color" : "red", "model" : "slim" } }, { "_index" : "shirts", "_type" : "_doc", "_id" : "4", "_score" : 0.0, "_source" : { "brand" : "gucci", "color" : "red", "model" : "hat" } } ] }, "aggregations" : { "color_red" : { "doc_count" : 2, "models" : { "doc_count_error_upper_bound" : 0, "sum_other_doc_count" : 0, "buckets" : [ { "key" : "hat", "doc_count" : 1 }, { "key" : "slim", "doc_count" : 1 } ] } }, "colors" : { "doc_count_error_upper_bound" : 0, "sum_other_doc_count" : 0, "buckets" : [ { "key" : "red", "doc_count" : 2 }, { "key" : "black", "doc_count" : 1 }, { "key" : "green", "doc_count" : 1 }, { "key" : "white", "doc_count" : 1 } ] } } }
我们看到返回结果中:
查询结果返回了:
- 2件商品(1件红色的衬衫,1顶红色的帽子)。
- colors聚合返回了4种颜色,及每种颜色的商品数量
- color_red聚合返回了2种商品,及这2种商品下对应的商品数量。
Rescore filtered search results(对查询结果重新打分)
rescore可以通过对query和post_filter的结果,重新进行排序,从而提高查询结果的精度。因为只是对结果重新排序,所以速度肯定也比对所有查询结果进行排序要快。es在每个碎片上执行一个rescore请求,然后它返回其结果,再由处理整体搜索请求的节点排序。目前,rescore API只有一个实现:rescore,它与query结合使用来调整评分。rescore的使用示例如下:
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 } } }
rescore只对query和post_filter阶段,返回的Top-K个结果执行二次打分。每个碎片上要检查的文档数量,可以由window_size参数控制,该参数默认为10。
默认情况下,原始查询和rescore查询的分数会线性组合,为每个文档生成最终的_score。原始查询和rescore查询的相对重要性,可以分别通过query_weight和rescore_query_weight来控制。两者的默认值都为1。
分数的组合方式可以通过score_mode来控制:
| Score Mode | Description |
|---|---|
|
|
将原始评分和rescore分数相加。 |
|
|
将原始评分和rescore分数相乘. 这种模式对 |
|
|
取原始评分和rescore分数的平均数。 |
|
|
取原始评分和rescore分数的最大值。 |
|
|
取原始评分和rescore分数的最小值。 |
Multiply rescore(在查询中使用多个rescore)
第一个rescore,获取query的结果,第二个rescore获取第一个rescore的结果,以此类推。第二个rescore将“看到”由第一个rescore完成的排序,因此可以在第一个rescore上使用一个大窗口(比如100条数据)将文档拉到第二个rescore的一个更小的窗口中(比如10条数据)。使用示例如下:
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)" } } } } } } ] }
浙公网安备 33010602011771号