如何使Top Hits聚合结果按major_num字段实现去重多样化?
这个问题确实有点棘手,因为top_hits聚合确实不支持嵌套子聚合来做去重。不过我们可以换个思路,先通过major_num的terms聚合来实现每个值的唯一性,再在每个唯一的major_num分组里取一条文档,最终组合成每个folder_id下的结果。
具体的查询DSL可以这么写:
GET /template/template/_search { "size": 0, "query": { "bool": { "filter": [ { "term": { "status": 1 } } ] } }, "aggs": { "folder": { "terms": { "field": "folder_id", "size": 10 }, "aggs": { "unique_major_num": { "terms": { "field": "major_num", "size": 5 // 这里设置你需要的每个folder_id下最多返回多少个不同的major_num文档 }, "aggs": { "single_doc_per_major": { "top_hits": { "size": 1, "_source": ["major_num", "tid", "folder_id"], // 按需指定返回的字段 "sort": [{"tid": "desc"}] // 可选:指定每个major_num下取哪条文档,比如按tid降序取最新的 } } } } } } } }
思路解释:
- 外层聚合:先按
folder_id分组,和你原来的逻辑一致,获取目标文件夹分组。 - 中间层聚合:在每个folder分组内,用
terms聚合按major_num分组——这一步是核心,因为terms聚合本身会把相同major_num的文档归到同一个bucket,天然保证了每个major_num唯一。这里的size参数控制每个folder下最多返回多少个不同的major_num结果。 - 内层top_hits:在每个
major_num的bucket里,用top_hits取1条文档(size:1),你可以通过sort参数指定取这条文档的规则(比如按时间、tid排序取最新/最早的)。
额外优化:
如果需要对每个folder下的不同major_num文档进行排序(比如按major_num大小或文档的某个字段排序),可以给中间层的terms聚合加上排序规则,比如:
"unique_major_num": { "terms": { "field": "major_num", "size": 5, "order": { "single_doc_per_major.tid": "desc" } // 引用top_hits里的排序字段来排序bucket }, "aggs": { "single_doc_per_major": { "top_hits": { "size": 1, "_source": ["major_num", "tid", "folder_id"], "sort": [{"tid": "desc"}] } } } }
这样返回的每个folder分组下,不同major_num的文档会按照你指定的规则排序。
最后需要注意:如果你的major_num可能有非常多不同的值,要确保unique_major_num的size参数设置足够大,避免遗漏你需要的结果。
内容的提问来源于stack exchange,提问作者user8510613
相关产品推荐
相关产品推荐

