ES 6.x时区日期直方图脚本问题:5.x兼容脚本在6.2版本失效
解决Elasticsearch 6.2中时区日期直方图聚合的问题
嘿,这个问题我之前帮人排查过!你的聚合在ES 6.2里跑不起来,主要是两个核心变化导致的:
一是Groovy脚本在ES 5.4之后就被默认禁用,到6.x版本直接移除支持了,原来的lang: groovy肯定行不通;二是ES 6.x对日期类型的脚本处理API做了大调整,原来依赖的Joda时间类操作方式已经不再适用。
给你两个解决方案,优先选第一个,性能更好还不用写脚本:
方案一:用原生date_histogram的时区支持(推荐)
ES 6.x开始,date_histogram聚合已经原生支持指定时区,完全不需要脚本就能实现按目标时区统计小时分布,代码更简洁性能也更高:
"aggregations": { "time": { "date_histogram": { "field": "write_at", "calendar_interval": "hour", "time_zone": "+09:00", "format": "HH", "extended_bounds": { "min": "00:00", "max": "23:00" }, "order": { "_key": "asc" } } } }
关键调整说明:
- 用
calendar_interval: hour替代原来的interval: 1(ES6+推荐使用日历对齐的间隔,更符合时间统计逻辑) - 直接通过
time_zone参数指定目标时区,无需手动转换 - 用
format: HH把聚合后的时间戳格式化为小时数,和你原来的需求一致 extended_bounds用时间字符串00:00和23:00来限定输出区间,确保0-23点的完整结果
方案二:改用Painless脚本(适用于必须用脚本的场景)
如果因为特殊需求必须用脚本实现,那就换成ES6+默认支持的Painless脚本,调整日期处理的语法:
"aggregations": { "time": { "histogram": { "script": { "source": "ZonedDateTime zdt = doc['write_at'].value.atZone(ZoneId.of(params.tz)); return zdt.getHour();", "params": { "tz": "+09:00" } }, "interval": 1, "offset": 0, "order": { "_key": "asc" }, "extended_bounds": { "min": 0, "max": 23 } } } }
关键调整说明:
- 脚本语言换成Painless(ES6+默认支持,无需额外配置)
- 用
source替代原来的inline参数(ES6+脚本参数命名规范调整) - 使用Java 8的
ZonedDateTime和ZoneId类来处理时区转换,替代原来的Joda时间API - 通过
doc['write_at'].value获取日期字段值,再转换为带目标时区的对象后提取小时数
如果你的ES集群做了严格的脚本权限控制,需要确保script.painless.regex.enabled等相关配置是开启的(默认是允许的,除非管理员做了限制)。
内容的提问来源于stack exchange,提问作者J.Done
相关产品推荐
相关产品推荐

