Elasticsearch分组聚合仅返回前10结果,如何实现分页?
Elasticsearch Top Hits聚合全量结果与分页实现
你好!我来帮你解决这两个问题——获取剩余的7个分组结果,以及实现每页5个产品的聚合分页。
一、获取剩余的7个分组结果
你当前的请求里,terms聚合默认只返回前10个bucket(这是Elasticsearch的默认配置),响应里的sum_other_doc_count:7就代表还有7个bucket没被返回。要拿到所有分组,只需要给terms聚合设置一个足够大的size值,比如直接设为17(10+7),或者根据你的数据总量设一个更大的安全值(比如100,如果总产品数不多的话)。
修改后的请求示例:
{ "query": { "bool": { "must": [ { "match_phrase_prefix": { "title": "Fortune" } } ] } }, "aggs": { "by_district": { "terms": { "field": "product_id", "size": 17 // 设置为总bucket数,这里是10+7=17 }, "aggs": { "tops": { "top_hits": { "size": 1 } } } } }, "from": 0, "size": 0 }
这样就能拿到所有17个产品分组的结果了。
二、实现每页5个产品的聚合分页
普通的from/size分页不适用于聚合结果,这里推荐使用Composite聚合来实现聚合分页,它专门用于对聚合结果进行高效的分页查询,支持翻页获取后续的bucket。
第一页(前5个分组)请求:
{ "query": { "bool": { "must": [ { "match_phrase_prefix": { "title": "Fortune" } } ] } }, "aggs": { "by_district": { "composite": { "size": 5, // 每页返回5个bucket "sources": [ { "product_id": { "terms": { "field": "product_id" } } } ] }, "aggs": { "tops": { "top_hits": { "size": 1 } } } } }, "size": 0 }
响应里会包含after_key字段,它是当前页最后一个bucket的key,用来作为下一页的游标。比如假设第一页最后一个bucket的key是"product_id": "1026",那么第二页的请求就需要带上这个after参数。
第二页请求(基于第一页的after_key):
{ "query": { "bool": { "must": [ { "match_phrase_prefix": { "title": "Fortune" } } ] } }, "aggs": { "by_district": { "composite": { "size": 5, "sources": [ { "product_id": { "terms": { "field": "product_id" } } } ], "after": { "product_id": "1026" } // 第一页返回的after_key }, "aggs": { "tops": { "top_hits": { "size": 1 } } } } }, "size": 0 }
第三页请求(基于第二页的after_key):
以此类推,直到返回的结果中没有after_key,就说明已经拿到了所有分组。第三页会返回剩下的7个结果(因为17-5-5=7)。
关键说明
- Composite聚合的好处是避免了普通terms聚合分页的性能问题,尤其是数据量大的时候,它不会一次性加载所有bucket,而是通过游标逐步获取。
- 如果你的产品id是数值类型,
after参数里的value也要用数值类型,保持和字段类型一致。
内容的提问来源于stack exchange,提问作者user6051114
相关产品推荐
相关产品推荐

