如何在Elasticsearch中获取高于平均值数据?QueryDSL问题咨询
嘿,我来帮你搞定这个Elasticsearch的问题!你想要实现类似SQL里筛选出score高于平均值的文档,对吧?我分两种情况给你详细说明:一种是高于整个索引的score平均值,另一种是你现有聚合里每个分组内高于组内平均值的文档。
一、获取高于整个索引score平均值的文档
这种就对应你给出的SQL语句SELECT * FROM index WHERE score > (SELECT AVG(score) FROM index),有两种实现方式:
1. 分步查询(推荐,性能更优)
先单独查询出整个索引的score平均值,再用这个值作为过滤条件查询文档:
- 第一步:获取整体平均值
GET index/_search { "size": 0, "aggs": { "total_avg_score": { "avg": { "field": "score" } } } }
执行后你会得到类似"total_avg_score": {"value": 78.5}的结果,把这个平均值记下来。
- 第二步:筛选出score高于平均值的文档
用range查询直接过滤,比如平均值是78.5:
GET index/_search { "query": { "range": { "score": { "gt": 78.5 } } } }
2. 单次脚本查询(实时计算,适合小索引)
如果不想分两步,也可以用Painless脚本在查询里实时计算并过滤,但这种方式在大索引上性能会差一些:
GET index/_search { "query": { "script": { "script": { "source": "doc['score'].value > _index['index'].avg('score')", "lang": "painless" } } } }
二、获取每个分组内高于组内平均值的文档
如果你想要的是每个group分组里,score高于该组平均值的文档,可以基于你现有的聚合修改,添加过滤和结果返回的逻辑:
GET index/_search { "size": 0, "aggs": { "groupByClass": { "terms": { "field": "group" }, "aggs": { // 计算当前分组的score平均值 "avgGroup": { "avg": { "field": "score" } }, // 过滤出当前分组内score高于组平均的文档 "docs_above_group_avg": { "filter": { "script": { "source": "doc['score'].value > aggregations.avgGroup.value" } }, // 返回这些文档的详情,size按需调整 "aggs": { "top_docs": { "top_hits": { "size": 100 } } } } } } } }
这个查询会把每个group分组下,score高于该组平均值的文档都通过top_hits返回给你,你可以根据需求调整top_hits里的size参数来控制每个分组返回的文档数量。
注意事项
- 确保你的
score字段是数值类型(比如integer、float),不然平均值聚合和脚本过滤都会报错; - 大索引下优先用分步查询的方式,避免实时计算平均值带来的性能损耗;
- 如果需要返回大量文档,记得合理设置
size和分页参数,避免内存溢出。
内容的提问来源于stack exchange,提问作者박주미
相关产品推荐
相关产品推荐

