ElasticSearch:聚合时如何拼接数组元素?
如何在Elasticsearch中聚合拼接数组字段
当然能实现!你要的这种按email聚合并拼接所有相关error_codes数组的需求,用Elasticsearch的scripted_metric聚合就能搞定——这是处理这类自定义数组合并场景的绝佳方案,比普通的数值聚合灵活得多。
完整的聚合DSL示例
下面是直接可用的查询语句,会按照email分组,把每个分组下所有文档的error_codes数组合并成一个大数组:
{ "size": 0, // 不需要返回原始文档,只看聚合结果 "aggs": { "email_groups": { "terms": { "field": "email.keyword" // 注意用keyword类型做精确分组 }, "aggs": { "concat_error_codes": { "scripted_metric": { "init_script": "state.error_codes = []", // 初始化分组的状态数组 "map_script": "state.error_codes.addAll(doc['error_codes'].values)", // 收集每个文档的error_codes "combine_script": "return state.error_codes", // 合并当前分片内的结果 "reduce_script": "def merged = []; for (s in states) { merged.addAll(s); } return merged;" // 合并所有分片的结果 } } } } } }
脚本逻辑说明
每个脚本的作用一目了然:
init_script:为每个email分组创建一个空数组,用来存放后续收集到的错误码。map_script:遍历当前分组下的每一篇文档,把文档里的error_codes数组所有元素添加到状态数组中。combine_script:在单个分片内,把该分片收集到的数组返回,准备进行跨分片合并。reduce_script:把所有分片返回的数组合并成一个最终的大数组,这就是你要的拼接结果。
返回结果示例
执行上述查询后,会得到和你期望结构一致的结果:
{ "aggregations": { "email_groups": { "buckets": [ { "key": "user@mail.com", "concat_error_codes": { "value": ["12.03","23.22","44.45","34.2","23.22","44.45"] } } ] } } }
可选:给数组去重
如果需要去掉重复的错误码,只需要修改reduce_script(或combine_script),用哈希表来去重:
"reduce_script": "def merged = new HashSet(); for (s in states) { merged.addAll(s); } return merged.toArray();"
这样返回的数组就不会有重复元素了。
注意事项
- 确保
error_codes字段的类型支持脚本访问:如果是text类型,需要开启fielddata;如果是keyword类型则直接可用。 - 如果
error_codes是嵌套字段,需要调整脚本中的访问路径(比如doc['nested_field.error_codes'].values)。
内容的提问来源于stack exchange,提问作者Chili
相关产品推荐
相关产品推荐

