Elasticsearch聚合滚动查询返回空结果,求原因及解决方法
Elasticsearch滚动查询不支持聚合桶分页?问题分析与解决方案
首先直接给结论:Elasticsearch的Scroll滚动查询并不支持对普通聚合(比如你用的terms聚合)的结果桶进行分页,这是你后续调用scrollId返回空结果的核心原因。
为什么你的操作无效?
你当前的思路存在两个关键误区:
- Scroll的设计目标是分页遍历搜索结果(
hits数组),而非聚合结果。你设置了size:0,所以第一次请求的hits本来就是空的,后续滚动自然没有更多hits返回。 terms聚合的size参数只是控制单次返回的桶数量(前100个排序后的桶),它不会和Scroll配合来分批获取剩余的桶——普通聚合的结果是基于全量数据集一次性计算的,Scroll无法介入这个过程。
正确的解决方案:用Composite聚合实现聚合桶分页
如果你需要分批获取大量聚合桶(比如数百万级的分组),Elasticsearch专门提供了Composite聚合来支持这个场景,它可以和Scroll结合实现稳定的聚合桶分页。
第一步:发起初始Composite聚合请求
请求URL依然用http://my.servers.ip:9200/index_name/doc_type/_search?scroll=1m,请求体修改为:
{ "_source": false, "size": 0, "aggs": { "paginated_groups": { "composite": { "size": 100, "sources": [ { "group_by_target": { "terms": { "field": "somePropertyIWantToGoupBy" } } } ] }, "aggs": { "unique_category_count": { "cardinality": { "field": "someCategoryIWantUniqueCount" } } } } } }
composite的sources定义你要分组的字段(对应原来的terms聚合字段)size控制每批返回的聚合桶数量- 嵌套的
unique_category_count保持你原来的基数统计需求
第二步:用ScrollId获取下一批聚合桶
拿到初始请求返回的_scroll_id后,后续的滚动请求可以这样发送(请求体只需指定scroll参数和scrollId):
{ "scroll": "1m", "scroll_id": "你的scrollId值" }
每次请求会返回下一批100个聚合桶,直到返回的aggregations.paginated_groups.buckets为空,说明所有桶都遍历完成。
关键区别说明
terms聚合返回的是排序后的Top N桶(默认按文档数降序),无法保证遍历所有桶(尤其是当桶数量远大于size时,会丢失低频桶)。Composite聚合是基于组合键的全量遍历,可以稳定地获取所有聚合桶,不会丢失数据,专门为大数据量的聚合分页场景设计。
内容的提问来源于stack exchange,提问作者Noam Segev
相关产品推荐
相关产品推荐

