Elasticsearch:在collapse/inner_hits查询中获取分组真实总条数
解决Elasticsearch折叠后获取分组总数及分页问题
核心思路
collapse本质是对查询结果的后处理,无法直接返回分组的真实数量。要同时实现按number分组取最新文档、获取分组总数、支持分页,推荐用Terms聚合+Top Hits聚合的组合方案,深分页场景则用Composite聚合。
方案一:Terms + Top Hits聚合(浅分页适用)
这个方案可直接拿到分组总数,同时获取每组最新文档,还能通过size和from控制分页。
查询示例
{ "size": 0, // 无需顶层hits,仅返回聚合结果 "aggs": { "group_by_number": { "terms": { "field": "number", "size": 10, // 每页返回10组,对应分页size "from": 20, // 从第20组开始,对应分页from "order": { "latest_doc": "desc" } // 按每组最新文档的时间排序 }, "aggs": { "latest_doc": { "top_hits": { "size": 1, "sort": [{"timestamp": "desc"}] // 取每组timestamp最新的文档 } }, "group_count": { "value_count": { "field": "number" // 每组的文档计数 } } } }, "total_groups": { "cardinality": { "field": "number", "precision_threshold": 100000 // 控制基数统计精度,值越大越准但内存消耗越高 } } } }
结果解析
aggregations.total_groups.value:分组的真实总条数,用于计算分页总页数aggregations.group_by_number.buckets:每页的分组数据,每个桶包含:key:分组的number值group_count.value:该组的文档总数latest_doc.hits.hits[0]:该组最新的文档内容
方案二:Composite聚合(深分页适用)
如果分组数量极大(超过10000),Terms聚合的from参数会受内存限制无法支持深分页,此时用Composite聚合实现高效游标式分页。
查询示例
{ "size": 0, "aggs": { "group_by_number": { "composite": { "size": 10, "sources": [ {"number": {"terms": {"field": "number"}}} ], "after": {"number": "上一页最后一个分组的number值"} // 深分页游标 }, "aggs": { "latest_doc": { "top_hits": { "size": 1, "sort": [{"timestamp": "desc"}] } }, "group_count": { "value_count": { "field": "number" } } } }, "total_groups": { "cardinality": { "field": "number", "precision_threshold": 100000 } } } }
注意事项
Composite聚合通过after参数实现游标式分页,规避深分页的性能问题- 分组总数仍通过
cardinality聚合获取,需根据数据规模调整精度阈值
为何放弃collapse?
collapse仅用于折叠查询结果中的重复项,不会修改顶层hits.total(始终为匹配的总文档数),也无法直接提供分组总数,更不支持基于分组的分页,因此聚合方案更适配分页+分组总数的需求。
内容的提问来源于stack exchange,提问作者Sebastian Zaklada
相关产品推荐
相关产品推荐

