Elasticsearch 7.17.7按每3行分组求age平均值的方案咨询
Elasticsearch 7.17.7 分组求平均值解决方案
针对你提出的先按score升序排序,再每3行计算age平均值的需求,可以使用Elasticsearch的scripted_metric聚合来实现,以下是具体的查询DSL:
GET /your_index/_search { "size": 0, "aggs": { "age_group_avg": { "scripted_metric": { "init_script": "state.docs = []", "map_script": "state.docs.add(['age': doc.age.value, 'score': doc.score.value])", "combine_script": """ // 按score字段升序排序文档 state.docs.sort((a, b) -> a.score.compareTo(b.score)); def result = []; // 每3个文档为一组计算平均值 for (int i = 0; i < state.docs.size(); i += 3) { def endIdx = Math.min(i + 3, state.docs.size()); def group = state.docs.subList(i, endIdx); def ages = group.stream().mapToInt(doc -> doc.age).toArray(); def sum = Arrays.stream(ages).sum(); def avg = sum / ages.length; // 拼接成期望的格式字符串 def expr = "(" + Arrays.stream(ages).mapToObj(String::valueOf).collect(Collectors.joining("+")) + ")/" + ages.length + " = " + avg; result.add(expr); } return result; """, "reduce_script": "return states.get(0);" } } } }
关键部分说明
size: 0:不返回原始文档,仅返回聚合结果,提升查询效率。scripted_metric聚合:init_script:初始化一个空列表,用于存储每个文档的age和score数据。map_script:遍历每个文档,将age和score以键值对形式加入列表。combine_script:- 先对列表中的文档按
score升序排序,匹配你的排序需求。 - 循环将文档按每3个一组划分,计算每组年龄的总和与平均值,并拼接成你期望的格式字符串。
- 先对列表中的文档按
reduce_script:由于你使用单节点集群,直接取第一个分片的计算结果即可。
查询结果示例
执行上述查询后,返回的聚合结果会包含以下内容:
{ ... "aggregations": { "age_group_avg": { "value": [ "(15+17+22)/3 = 18", "(13+16+19)/3 = 16", "(17+15+25)/3 = 19" ] } } }
内容的提问来源于stack exchange,提问作者mhsankar
相关产品推荐
相关产品推荐

