Elasticsearch V5 聚合查询实现按Number字段分组取每组第一条数据
解决Elasticsearch 5.x中按字段分组去重并保留每组第一条数据的问题
嘿,针对你遇到的重复数据问题,在Elasticsearch 5.x里我们可以通过terms聚合搭配top_hits子聚合来实现按Number字段分组,并且每组只保留第一条数据的需求。
完整查询语句
把你原来的bool查询和聚合逻辑结合起来,最终的DSL是这样的:
{ "query": { "bool": { "must": [ { "term": { "Name": { "value": "Self", "boost": 1.0 } } } ], "filter": [ { "terms": { "Number": ["111", "222"] } } ] } }, "aggs": { "group_by_number": { "terms": { "field": "Number", "size": 1000 // 这里设置足够大的数值,确保能覆盖所有需要分组的Number值 }, "aggs": { "first_hit": { "top_hits": { "size": 1, // 每组只取第一条数据 "_source": ["Name", "Number"] // 只返回需要的字段,减少数据量 } } } } }, "size": 0 // 关闭原始hits的返回,只保留聚合结果 }
结果说明
执行这个查询后,你会得到类似这样的聚合结果:
{ ..., "aggregations": { "group_by_number": { "buckets": [ { "key": "222", "doc_count": 2, "first_hit": { "hits": { "hits": [ { "_source": { "Name": "Self", "Number": 222 } } ] } } }, { "key": "111", "doc_count": 2, "first_hit": { "hits": { "hits": [ { "_source": { "Name": "Self", "Number": 111 } } ] } } } ] } } }
你只需要遍历aggregations.group_by_number.buckets,取出每个bucket里first_hit.hits.hits[0]._source的内容,就能得到你想要的去重后的数据列表。
补充说明
- 如果需要指定每组“第一条数据”的规则(比如按创建时间最新/最早排序),可以在
top_hits里添加sort参数,比如:"top_hits": { "size": 1, "_source": ["Name", "Number"], "sort": [{"create_time": "desc"}] // 按create_time倒序,取最新的一条 } terms聚合里的size参数要设置得足够大,确保能包含所有你需要分组的Number值,避免遗漏数据。
内容的提问来源于stack exchange,提问作者Prashant Gupta
相关产品推荐
相关产品推荐

