Elasticsearch聚合差值计算失效及排序需求技术求助
问题:Elasticsearch聚合中Bucket Script未生效及差值排序问题
我需要从一组含start和end日期的数据中,找出随时间变化的最大增幅和最大降幅。思路是先筛选出两个时间段内的活跃项,计算两者的差值后排序取最值,但实现时遇到了问题。
以下是我的聚合查询:
{ "aggs": { "myAgg": { "aggs": { "timeBuckets": { "filters": { "filters": { "_start": { "bool": { "must": [ { "range": { "start": { "format": "yyyy-MM-dd'T'HH:mm:ss", "gte": "2016-10-01T00:00:00", "lte": "2024-12-10T23:59:59" } } }, { "range": { "end": { "format": "yyyy-MM-dd'T'HH:mm:ss", "gte": "2024-12-09T00:00:00" } } } ] } }, "_end": { "bool": { "must": [ { "range": { "start": { "format": "yyyy-MM-dd'T'HH:mm:ss", "gte": "2016-10-01T00:00:00", "lte": "2025-01-07T23:59:59" } } }, { "range": { "end": { "format": "yyyy-MM-dd'T'HH:mm:ss", "gte": "2025-01-06T00:00:00" } } } ] } } } } }, "diff": { "bucket_script": { "buckets_path": { "start": "timeBuckets._start", "end": "timeBuckets._end" }, "script": "params.end - params.start" } } }, "terms": { "field": "myItems.label", "shard_size": 1000, "size": 10 } } } }
执行查询后没有报错,能按指定字段聚合并得到预期的_start和_end桶,但差值计算没有生效,输出中看不到diff字段。示例输出如下:
{ "aggregations": { "myAgg": { "doc_count_error_upper_bound": 0, "sum_other_doc_count": 1297, "buckets": [ { "key": "Foo", "doc_count": 287, "timeBuckets": { "buckets": { "_end": { "doc_count": 190 }, "_start": { "doc_count": 215 } } } } ] } } }
请问为什么Bucket Script没有作用?另外,如何基于计算出的差值进行排序?
解答
一、Bucket Script未生效的原因
你在buckets_path里直接引用timeBuckets._start和timeBuckets._end是错误的,因为这两个是filters聚合的桶对象,而Bucket Script需要明确引用桶内的具体度量值(比如doc_count)。
正确的写法需要通过>符号指定要获取的桶内字段,修改后的buckets_path如下:
"buckets_path": { "start": "timeBuckets._start>doc_count", "end": "timeBuckets._end>doc_count" }
这样Bucket Script才能正确读取两个时间段的文档数量,进而完成差值计算。
二、基于差值排序的实现
要基于diff字段排序,只需在terms聚合中添加order参数,直接引用diff聚合的结果即可。同时建议调大size参数(比如设为10000),避免遗漏可能的极值项。
修改后的完整聚合查询如下:
{ "aggs": { "myAgg": { "aggs": { "timeBuckets": { "filters": { "filters": { "_start": { "bool": { "must": [ { "range": { "start": { "format": "yyyy-MM-dd'T'HH:mm:ss", "gte": "2016-10-01T00:00:00", "lte": "2024-12-10T23:59:59" } } }, { "range": { "end": { "format": "yyyy-MM-dd'T'HH:mm:ss", "gte": "2024-12-09T00:00:00" } } } ] } }, "_end": { "bool": { "must": [ { "range": { "start": { "format": "yyyy-MM-dd'T'HH:mm:ss", "gte": "2016-10-01T00:00:00", "lte": "2025-01-07T23:59:59" } } }, { "range": { "end": { "format": "yyyy-MM-dd'T'HH:mm:ss", "gte": "2025-01-06T00:00:00" } } } ] } } } } }, "diff": { "bucket_script": { "buckets_path": { "start": "timeBuckets._start>doc_count", "end": "timeBuckets._end>doc_count" }, "script": "params.end - params.start" } } }, "terms": { "field": "myItems.label", "shard_size": 10000, "size": 10000, "order": { "diff": "desc" // 按差值降序排序,取增幅最大;要取降幅最大则设为"asc" } } } } }
修改后执行查询,每个myAgg的桶里会显示diff字段,并且会按差值排序,你可以直接取排序后的前几项(最大增幅)或后几项(最大降幅)。
内容的提问来源于stack exchange,提问作者Matt Burland
相关产品推荐
相关产品推荐

