Elasticsearch:能否对过滤聚合排序及预过滤是否有价值?
Elasticsearch聚合排序与前置过滤问题解答
先看一下你提供的查询语句:
GET item_*/_search { "size": 0, "query": { "bool": { "filter": [ { "terms": { "page_id": [ 1, 652, ... ] } } ] } }, "aggs": { "group1": { "filter": { "terms": { "page_id": [ 1, 652,... ] } }, "aggs": { "sum_items_likes": { "sum": { "field": "reactions.likes" } }, ... } }, "group2": ... } }
针对你的两个问题,我来逐一解答:
1. 能不能按sum_items_likes给filter聚合排序?
完全可以!这里要用到Elasticsearch的管道聚合bucket_sort,它专门用来对父聚合生成的桶进行排序。
不过首先得调整一下你的聚合结构:把所有的group1、group2这类filter聚合放到一个filters聚合下面,然后在这个filters聚合中添加bucket_sort管道聚合,指定按sum_items_likes排序。
给你修改后的示例查询:
GET item_*/_search { "size": 0, "query": { "bool": { "filter": [ { "terms": { "page_id": [ 1, 652, ... ] } } ] } }, "aggs": { "all_filter_groups": { "filters": { "filters": { "group1": { "terms": { "page_id": [ 1, 652,... ] } }, "group2": { // 这里填group2的过滤条件 } // 其他group依次添加 } }, "aggs": { "sum_items_likes": { "sum": { "field": "reactions.likes" } }, "sort_by_likes_sum": { "bucket_sort": { "sort": [ { "sum_items_likes": { "order": "desc" } } // 降序排序,换成"asc"就是升序 ] } } } } } }
这样返回结果里,all_filter_groups.buckets就会按照每个group的点赞总和从高到低排列了。只要每个group都有sum_items_likes这个子聚合,不管其他子聚合是否不同,这个排序逻辑都能正常工作。
2. 前置bool filter过滤page_id有没有价值?
必须有,而且价值还不小!主要体现在这几个方面:
- 减少聚合计算量:前置过滤会先把不符合
page_id条件的文档直接排除掉,后续的聚合操作只需要处理剩下的符合条件的文档,数据量小了,Elasticsearch的计算压力自然就降低了,尤其是当你的索引有大量数据时,这个优化效果会很明显。 - 简化查询逻辑:看你的原始查询,每个group的filter里都重复写了
page_id的过滤条件,前置过滤后,每个group只需要关注自己特有的过滤规则(如果有的话),不用重复写相同的page_id筛选,查询结构更简洁,后期维护也更方便。 - 提升整体性能:查询阶段的过滤是利用Elasticsearch的倒排索引来快速定位文档的,效率非常高;而如果不在前置过滤,每个聚合单独过滤的话,相当于对整个数据集再做一次筛选,性能肯定不如前置过滤来得好。
当然,如果某个group的page_id范围和前置过滤的范围不一样,那你可以单独调整该group的过滤条件,但如果所有group的page_id都包含在前置过滤的集合里,那前置过滤绝对是最优的选择。
内容的提问来源于stack exchange,提问作者JosselinH
相关产品推荐
相关产品推荐

