如何对Elasticsearch中flattened类型字段进行键值文档计数聚合?
问题描述
我们有如下Elasticsearch文档:
POST bug_reports/_doc/1 { "title": "Results are not sorted correctly.", "labels": { "priority": "urgent", "product": "A" } }
其中labels字段为flattened类型,无法预知其键的数量和名称。
当前执行聚合后得到的桶结构如下:
{ "buckets": [ { "key": "urgent", "doc_count": 27705 }, { "key": "no urgent", "doc_count": 705 } ] }
但我们希望生成包含flattened字段内每个键的键名、对应值及文档计数的聚合结构,示例如下:
{ "buckets": [ { "key": "priority", "values": [ { "key": "urgent", "doc_count": 27705 }, { "key": "no urgent", "doc_count": 705 } ] }, { "key": "product", "values": [ { "key": "A", "doc_count": 3215 } ] } ] }
请问这是否可行?已查阅composite和multi_terms聚合的相关文档,但它们似乎适用于其他场景。
解答
这完全可行,你可以通过两层terms聚合配合脚本提取flattened字段的键名来实现需求。具体的聚合DSL如下:
GET bug_reports/_search { "size": 0, "aggs": { "label_keys": { "terms": { "script": { "source": "for (entry in params._source.labels.entrySet()) { emit(entry.getKey()) }" }, "size": 1000 // 根据实际键的数量调整 }, "aggs": { "label_values": { "terms": { "script": { "source": "params._source.labels[doc['labels.key'].value]" }, "size": 1000 // 根据每个键对应的值数量调整 } } } } } }
说明:
- 外层
label_keys聚合:通过脚本遍历labels的所有键并emit,以此按键名分组,得到每个标签键的桶。 - 内层
label_values聚合:针对每个键名的桶,提取对应的值并统计每个值的文档数量。
如果你的Elasticsearch版本支持flattened字段的keys元数据,也可以简化外层聚合的脚本,直接使用field: "labels.keys"来替代脚本,效率会更高:
"label_keys": { "terms": { "field": "labels.keys", "size": 1000 }, // 内层聚合不变 }
执行上述聚合后,返回的结构会和你期望的一致,外层桶的key是标签键名,内层label_values的buckets就是对应的值和计数,你可以根据需要重命名聚合名称来匹配示例中的values字段。
内容的提问来源于stack exchange,提问作者georgeos
相关产品推荐
相关产品推荐

