Elasticsearch 中的 post_filter 后置过滤器
一、概述
post_filter 出现在聚合章节,描述 post_filter 的作用为:只过滤搜索结果,不过滤聚合结果
二、假设一个查询聚合的需求
假设我们的查询需求是:品牌为 ford 的汽车有哪些颜色
这个需求是容易实现的:先限定查询范围(品牌为 ford),再用类型为 terms 的桶对 color 字段做聚合;
1、用查询结果生成聚合结果,然后只返回聚合结果
只要设置 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
}
]
}
}
}
2、用查询结果生成聚合结果,然后返回聚合结果和查询结果
如果我们想在返回内容中包含查询结果,只要把 "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
}
]
}
}
}
3、用查询结果生成聚合结果,然后返回聚合结果和被再次过滤后的查询结果
第三种返回的聚合结果与前面两种一模一样,都是品牌为ford的汽车的颜色;
聚合结果生成完毕后,查询结果可以根据post_filter参数的设置而被再次过滤,例如品牌为ford的汽车,可以把其他颜色过滤掉,只要蓝色的,然后再返回,此时返回的查询结果中就只有品牌为ford并且颜色是blue的文档,具体的DSL如下
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。
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论