Elasticsearch 8.3.3索引Transform:如何让每组返回多行数据
Elasticsearch 8.3.3 Transform实现分组多行输出(无需重索引)
可以不用重索引实现需求,核心是利用Elasticsearch Transform的**数组展开(unfold)**特性,配合修正后的scripted_metric聚合返回数组结构,让每个分组的数组元素自动拆分为目标索引的独立文档。
原代码问题分析
你的现有reduce_script存在两个关键问题:
- 未定义
info变量,会直接导致脚本执行失败 - 即使返回数组,Transform默认会将整个数组作为单个字段存入单条文档,不会自动拆分为多行
修正方案
1. 修正scripted_metric聚合脚本
确保reduce_script生成独立的条目对象,每次循环新建对象避免引用复用(如果需要基于分组内的源文档计算指标,可替换示例中的硬编码值):
"aggregations": { "expanded_entries": { "scripted_metric": { "init_script": "state.docs = [];", "map_script": "state.docs.add(params['_source']);", "combine_script": "return state.docs", "reduce_script": """ ArrayList output = new ArrayList(); def groupDocs = states[0]; // 基于分组内的文档获取documentId,确保每个条目关联分组标识 def groupId = groupDocs[0].documentId; for (thr in [1,2,3]) { // 每次循环新建独立HashMap,避免引用覆盖 def entry = new HashMap(); entry['documentId'] = groupId; entry['a'] = 0F; entry['b'] = 0F; entry['c'] = 0F; entry['threshold'] = thr; // 可替换为基于groupDocs的计算逻辑,比如求和、平均值 // entry['a'] = groupDocs.stream().mapToFloat(doc -> doc.a).sum(); output.add(entry); } return output; """ } } }
2. 配置Transform的展开参数
在Transform定义中添加settings.unfold指定要展开的数组字段,同时关闭原源文档存储以优化性能:
{ "source": { "index": ["your-source-index"] }, "dest": { "index": "your-target-index" }, "pivot": { "group_by": { "documentId": { "terms": { "field": "documentId" } } }, "aggregations": { // 插入上面修正后的expanded_entries聚合代码 } }, "settings": { "docs_without_source": true, "unfold": "expanded_entries" } }
生效逻辑
scripted_metric的reduce_script返回一个包含多个条目的数组,每个条目对应目标索引的一行数据settings.unfold: "expanded_entries"会告诉Transform将该数组的每个元素拆分为独立的文档docs_without_source: true避免存储原源数据,只保留聚合生成的结构化条目
内容的提问来源于stack exchange,提问作者RunTheGauntlet
相关产品推荐
相关产品推荐

