如何在Elasticsearch中从timestamp提取对应时区的当地星期几
问题根因&修复方案
1. 字段缺失的核心原因
你配置的ingest pipeline存在两个可直接导致script处理器执行失败的问题,且你开启了ignore_failure: true,脚本出错后会直接跳过执行,因此目标字段不会生成:
- 语法错误:painless脚本第一行缺赋值等号,原代码
LocalDateTime local_time LocalDateTime.ofInstant(...)写法非法,正确应为LocalDateTime local_time = LocalDateTime.ofInstant(...) - 未做非空判断:如果geoip解析失败没有返回
client_geo.timezone字段,ZoneId.of()会直接抛出空指针异常,触发脚本跳过逻辑 - 额外注意:你示例中的
@timestamp值为43109942361111,换算后为3336年,若实际业务存在异常时间戳也可能触发时间转换失败
2. 搜索时报错No field found for [client_geo]的原因
- 映射配置不全:你仅手动添加了
client_geo.timezone的keyword类型,但未声明父级client_geo为object类型,且关闭动态映射的情况下,新写入的嵌套字段不会被自动识别 - 字段访问方式错误:脚本中
doc['client_geo']['timezone']的写法非法,ES的doc values访问嵌套字段需用.拼接全路径,正确写法为doc['client_geo.timezone'],且client_geo作为object类型本身不会生成doc values,因此直接访问doc['client_geo']会提示字段不存在
修复步骤
步骤1:修正ingest pipeline的script处理器配置
{ "script": { "description": "Extract details of Dates", "lang": "painless", "ignore_failure": true, "source": """ // 前置校验必要字段是否存在,避免空指针异常 if (ctx['@timestamp'] == null || ctx['client_geo'] == null || ctx['client_geo.timezone'] == null) { return; } LocalDateTime local_time = LocalDateTime.ofInstant(Instant.ofEpochMilli(ctx['@timestamp'].toInstant().toEpochMilli()), ZoneId.of(ctx['client_geo.timezone'])); int day_of_week = local_time.getDayOfWeek().getValue(); int hour_of_day = local_time.getHour(); int office_hours = -1; if (day_of_week >= 1 && day_of_week < 6 && hour_of_day >=7 && hour_of_day <=19) { office_hours = 1; } ctx['day_of_week'] = day_of_week; ctx['hour_of_day'] = hour_of_day; ctx['office_hours'] = office_hours; """ } }
步骤2:补全索引映射
因为你关闭了动态映射,需手动添加所有新增字段的映射:
PUT 你的索引名称/_mapping { "properties": { "client_geo": { "type": "object", "properties": { "timezone": {"type": "keyword"}, "continent_name": {"type": "keyword"}, "country_name": {"type": "keyword"}, "country_iso_code": {"type": "keyword"}, "region_iso_code": {"type": "keyword"}, "region_name": {"type": "keyword"}, "city_name": {"type": "keyword"}, "location": {"type": "geo_point"} } }, "day_of_week": {"type": "integer"}, "hour_of_day": {"type": "integer"}, "office_hours": {"type": "integer"} } }
步骤3:修正搜索脚本的字段访问逻辑
GET 你的索引名称/_search { "script_fields": { "day_of_week": { "script": "doc['@timestamp'].value.withZoneSameInstant(ZoneId.of(doc['client_geo.timezone'].value)).getDayOfWeek().getValue()" } } }
内容的提问来源于stack exchange,提问作者Saba Far
相关产品推荐
相关产品推荐

