Elasticsearch如何获取字段的唯一键值对(非聚合计数结果)
嘿,刚好处理过类似的需求,我来给你详细说说怎么在Elasticsearch里获取多字段的唯一键值对组合,完全匹配你要的去重效果!
方法1:多字段Terms聚合(小数据量首选)
如果你的数据量不算特别大,直接用脚本把两个字段拼接成唯一标识,再做Terms聚合就能拿到结果。
先看查询DSL:
{ "size": 0, // 不需要返回原始文档,只关注聚合结果 "aggs": { "unique_name_city_pairs": { "terms": { "script": { "source": "doc['name.keyword'].value + '|' + doc['city.keyword'].value" }, "size": 10000 // 按需调整,确保能覆盖所有唯一组合 } } } }
这里用|作为分隔符把name和city的精确值(必须用keyword类型,不然会分词出错)拼接成唯一字符串,每个聚合桶就对应一组唯一的name+city组合。之后你只需要把桶的key拆分回键值对就行,比如把james|chicago拆成{"name": "james", "city": "chicago"}。
方法2:Composite聚合(大数据量场景必备)
如果数据量很大,Terms聚合的size设太大容易引发内存问题,这时候用Composite聚合更稳妥——它支持分页获取所有唯一组合,不会一次性加载大量数据。
查询DSL如下:
{ "size": 0, "aggs": { "unique_pairs": { "composite": { "sources": [ { "name": { "terms": { "field": "name.keyword" } } }, { "city": { "terms": { "field": "city.keyword" } } } ] } } } }
这个聚合会直接返回结构化的键值对,每个桶的key就是你要的去重结果,比如:
"buckets": [ { "key": { "name": "james", "city": "chicago" }, "doc_count": 2 }, { "key": { "name": "james", "city": "san francisco" }, "doc_count": 1 }, { "key": { "name": "Mike", "city": "chicago" }, "doc_count": 1 }, ... ]
你只需要提取每个桶里的key部分就好。如果需要获取全部组合,可以通过after参数分页查询,直到返回的buckets为空。
重要提示
- 一定要确保
name和city字段有对应的keyword类型映射!text类型会被分词,根本没法做精确的聚合匹配,如果没有的话得先调整字段映射。 - 要是不需要聚合返回的
doc_count(也就是每个组合出现的次数),直接忽略这个字段就行,我们要的就是key里的内容。
内容的提问来源于stack exchange,提问作者Miguel Barrios
相关产品推荐
相关产品推荐

