如何在Elasticsearch中按单个字段的多值进行分组?
解决方案:单个字段多值分组(无需修改索引映射)
针对你的需求,不需要修改索引映射,完全可以通过脚本聚合或运行时字段实现单个字段多值的动态分组,以下是两种实用方案:
方案1:Script Terms 聚合(直接在聚合中处理)
这种方式最简洁,直接在terms聚合内通过脚本动态生成分组标识,无需额外定义字段:
{ "size": 0, "aggs": { "product_groups": { "terms": { "script": """ def product = doc['product'].value; // 按需调整分组规则:将fruit/veg归为一组,其他值保留原字段或统一归为other return ['fruit', 'veg'].contains(product) ? 'produce_group' : product; // 若需将非目标值统一归为一组,替换为: // return ['fruit', 'veg'].contains(product) ? 'produce_group' : 'other'; """ } } } }
- 核心逻辑:脚本判断
product字段值是否在目标列表中,匹配则返回统一分组键,否则返回原字段值(或自定义的"other")。 - 灵活性:运行时直接修改脚本中的数组(比如
['fruit', 'veg', 'furniture'])即可调整分组组合,完全适配字段值频繁变动的场景。
方案2:运行时字段(Runtime Fields)+ Terms 聚合
如果需要在多个聚合中复用分组规则,可先通过runtime_mappings动态生成分组字段,再基于该字段做聚合:
{ "size": 0, "runtime_mappings": { "product_group": { "type": "keyword", "script": """ def product = doc['product'].value; if (['fruit', 'veg'].contains(product)) { emit('produce_group'); } else { emit(product); // 其他值保留原字段值 // 统一归为其他组则替换为:emit('other'); } """ } }, "aggs": { "product_groups": { "terms": { "field": "product_group" } } } }
- 优势:分组逻辑集中定义,可在多个聚合、查询条件中复用
product_group字段。
注意事项
- 若
product是text类型,需使用doc['product.keyword'].value获取精确值(默认text字段会自动生成keyword子字段); - 脚本支持任意复杂的分组规则,比如按前缀、正则匹配分组,只需调整脚本逻辑即可。
内容的提问来源于stack exchange,提问作者Joey Yi Zhao
相关产品推荐
相关产品推荐

