赞
踩
《Elasticsearch 权威指南》中,post_filter出现在聚合章节,描述post_filter的作用为:只过滤搜索结果,不过滤聚合结果;
描述比较简单,还是用实例来加深理解吧。
以下是本次实例的环境信息,请确保您的Elasticsearch可以正常运行:
查询用到的数据是个名为cars的索引,里面保存了多条汽车销售记录,字段有品牌(make)、颜色(color)、价格(price)、售卖时间(sold)等,在elasticsearch-head查看数据如下图:
如果您想将上图中的数据导入到自己的es环境,请参考《Elasticsearch聚合学习之一:基本操作》,文中有详细的导入步骤;
对上述索引,假设我们的查询需求是:品牌为ford的汽车有哪些颜色
这个需求是容易实现的:先限定查询范围(品牌为ford),再用类型为terms的桶对color字段做聚合;
具体的DSL怎么写呢?随着我们想要的数据的不同,有不同的写法:
只要设置size参数为0,就不会返回查询结果(返回JSON中,hits.hits的数组长度为0):
GET /cars/transactions/_search { "size": 0, "query": { ---查询 "bool": { ---布尔查询 "filter": { ---用了过滤器 "term": { ---精确匹配 "make": "ford" ---匹配make字段为ford的文档 } } } }, "aggs": { "colors": { "terms": { ---桶类型为terms "field": "color" ---根据color字段聚合 } } } }
返回内容中只有聚合结果:
{ "took" : 144, "timed_out" : false, "_shards" : { "total" : 5, "successful" : 5, "skipped" : 0, "failed" : 0 }, "hits" : { "total" : 2, "max_score" : 0.0, "hits" : [ ] ---这里面是查询结果,现在长度为0 }, "aggregations" : { ---这里面是用前面的查询结果来做聚合的结果,所有品牌为ford的文档,根据颜色不同进入了两个桶 "colors" : { "doc_count_error_upper_bound" : 0, "sum_other_doc_count" : 0, "buckets" : [ { "key" : "blue", ---蓝色 "doc_count" : 1 }, { "key" : "green", ---绿色 "doc_count" : 1 } ] } } }
如果我们想在返回内容中包含查询结果,只要把"size": 0,这个参数去掉即可:
GET /cars/transactions/_search { "query": { ---查询 "bool": { ---布尔查询 "filter": { ---用了过滤器 "term": { ---精确匹配 "make": "ford" ---匹配make字段为ford的文档 } } } }, "aggs": { "colors": { "terms": { ---桶类型为terms "field": "color" ---根据color字段聚合 } } } }
返回的内容如下所示,hits.hits的内容不再为空,而是包含了查询结果,至于聚合结果和前面是一样的:
{ "took" : 39, "timed_out" : false, "_shards" : { "total" : 5, "successful" : 5, "skipped" : 0, "failed" : 0 }, "hits" : { "total" : 2, "max_score" : 0.0, "hits" : [ ---这个JSON数组的每个元素,都一个品牌字段为ford的文档 { "_index" : "cars", "_type" : "transactions", "_id" : "hVOQeGoBgL6DDzH6-9ay", "_score" : 0.0, "_source" : { "price" : 30000, "color" : "green", ---颜色是green "make" : "ford", "sold" : "2014-05-18" } }, { "_index" : "cars", "_type" : "transactions", "_id" : "ilOQeGoBgL6DDzH6-9ay", "_score" : 0.0, "_source" : { "price" : 25000, "color" : "blue", ---颜色是blue "make" : "ford", "sold" : "2014-02-12" } } ] }, "aggregations" : { "colors" : { "doc_count_error_upper_bound" : 0, "sum_other_doc_count" : 0, "buckets" : [ { "key" : "blue", "doc_count" : 1 }, { "key" : "green", "doc_count" : 1 } ] } } }
GET /cars/transactions/_search { "query": { "bool": { "filter": { "term": { "make": "ford" } } } }, "post_filter": { ---在生成了聚合结果后,对即将返回的查询结果做一次过滤 "term": { "color": "blue" ---过滤条件是只保留color字段为blue的文档 } }, "aggs": { "colors": { "terms": { "field": "color" } } } }
返回数据如下,可见聚合结果和前面两种一模一样,只是查询结果中只有color字段为blue的文档:
{ "took" : 13, "timed_out" : false, "_shards" : { "total" : 5, "successful" : 5, "skipped" : 0, "failed" : 0 }, "hits" : { "total" : 1, "max_score" : 0.0, "hits" : [ { "_index" : "cars", "_type" : "transactions", "_id" : "ilOQeGoBgL6DDzH6-9ay", "_score" : 0.0, "_source" : { "price" : 25000, "color" : "blue", "make" : "ford", "sold" : "2014-02-12" } } ] }, "aggregations" : { "colors" : { "doc_count_error_upper_bound" : 0, "sum_other_doc_count" : 0, "buckets" : [ { "key" : "blue", "doc_count" : 1 }, { "key" : "green", "doc_count" : 1 } ] } } }
至此,post_filter的基本功能已介绍完毕,如果只做查询不做聚合,post_filter的作用和我们常用的filter是类似的,但由于post_filter是在查询之后才会执行,所以post_filter不具备filter对查询带来的好处(忽略评分、缓存等),因此,在普通的查询中不要用post_filter来替代filter;
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。