如何在Elasticsearch中对列表内对象进行唯一结果聚合
问题:Elasticsearch中按关联的key-value对聚合
当前映射
"custom_metadata": { "properties": { "key": { "type": "keyword" }, "value": { "type": "keyword" } } }
已导入的数据
文档1
"custom_metadata": [ { "value": "NPL", "key": "schema" }, { "value": "SAPERP", "key": "system" } ]
文档2
"custom_metadata": [ { "value": "trial", "key": "schema" }, { "value": "Oracle", "key": "system" } ]
预期聚合结果
希望按每个key分组,得到对应的value集合,示例格式如下:
"schema": [ {"value": "NPL"}, { "value": "trial"} ], "system":[ {"value": "SAPERP"}, { "value": "Oracle"} ]
已尝试的聚合及问题
尝试过以下嵌套聚合:
"custom_metadata_key": { "terms": { "field": "custom_metadata.key" }, "aggregations": { "custom_metadata_value": { "terms": { "field": "custom_metadata.value" } } } }
但结果中每个key的分组里会包含所有value,而非对应关联的value,例如:
{ "key" : "schema", "doc_count" : 2, "custom_metadata_value" : { "doc_count_error_upper_bound" : 0, "sum_other_doc_count" : 0, "buckets" : [ { "key" : "Oracle", "doc_count" : 2 }, { "key" : "NPL", "doc_count" : 1 }, { "key" : "SAPERP", "doc_count" : 1 }, { "key" : "trial", "doc_count" : 1 } ] } }
解决方案
出现这个问题的核心原因是:默认的object类型会将数组中的对象扁平化存储,导致key和value失去关联关系。需要将custom_metadata字段改为nested类型,并配合nested聚合实现关联查询。
1. 修改字段映射为nested类型
更新后的映射如下:
"custom_metadata": { "type": "nested", // 标记为nested类型 "properties": { "key": { "type": "keyword" }, "value": { "type": "keyword" } } }
注意:修改映射后需要重新导入数据,否则旧数据不会生效。
2. 使用nested聚合查询
正确的聚合查询语句:
{ "size": 0, // 不需要返回原始文档,只取聚合结果 "aggs": { "nested_metadata": { "nested": { "path": "custom_metadata" // 指定nested字段的路径 }, "aggs": { "group_by_key": { "terms": { "field": "custom_metadata.key" }, "aggs": { "group_by_value": { "terms": { "field": "custom_metadata.value" } } } } } } } }
聚合结果示例
执行上述查询后,会得到每个key对应关联value的聚合结果:
{ "aggregations": { "nested_metadata": { "doc_count": 4, "group_by_key": { "buckets": [ { "key": "schema", "doc_count": 2, "group_by_value": { "buckets": [ {"key": "NPL", "doc_count": 1}, {"key": "trial", "doc_count": 1} ] } }, { "key": "system", "doc_count": 2, "group_by_value": { "buckets": [ {"key": "SAPERP", "doc_count": 1}, {"key": "Oracle", "doc_count": 1} ] } } ] } } } }
这个结果可以直接在服务端解析成你需要的格式。
内容的提问来源于stack exchange,提问作者Ashwini Kumar
相关产品推荐
相关产品推荐

