如何在ElasticSearch查询中将日期转为yyyyMMdd数字格式并返回至_source?
没问题,我来教你怎么把Elasticsearch里的ISO格式日期转成yyyyMMdd的数字格式返回~
核心思路是用Painless脚本完成日期拆分、补零拼接、转数字这几个步骤,下面给你几种常用的实现方式:
方式一:用脚本字段(Script Fields)返回目标格式
这种方式会在查询响应里新增一个独立字段,和原_source并列返回,不修改原始数据:
{ "query": { "match_all": {} }, "script_fields": { "updated_yyyyMMdd": { "script": { "lang": "painless", "source": """ // 获取日期对象 ZonedDateTime dt = doc['updated'].value; // 提取年、月、日 int year = dt.getYear(); int month = dt.getMonthValue(); // 推荐用getMonthValue()替代旧的getMonthOfYear() int day = dt.getDayOfMonth(); // 格式化拼接成yyyyMMdd字符串,再转成数字 return Long.parseLong(String.format("%04d%02d%02d", year, month, day)); """ } } }, "_source": ["updated"] // 可选:保留原updated字段,按需调整 }
执行后,响应里会多出fields.updated_yyyyMMdd字段,值就是你要的数字(比如20200104)。
方式二:用Runtime Field整合到_source中
如果希望目标字段直接出现在_source里,可以用查询时定义的Runtime Field:
{ "query": { "match_all": {} }, "runtime_mappings": { "updated_yyyyMMdd": { "type": "long", "script": """ ZonedDateTime dt = doc['updated'].value; int year = dt.getYear(); int month = dt.getMonthValue(); int day = dt.getDayOfMonth(); emit(Long.parseLong(String.format("%04d%02d%02d", year, month, day))); """ } }, "_source": ["updated", "updated_yyyyMMdd"] // 指定返回原字段和新增的runtime字段 }
这样返回的_source里就会同时包含原updated和格式化后的updated_yyyyMMdd数字字段。
方式三:修改你的排序脚本
如果需要在排序时使用这个数字,同时也要返回它,可以把排序脚本和脚本字段结合:
{ "query": { "match_all": {} }, "sort": [ { "_script": { "type": "number", "script": { "lang": "painless", "source": """ ZonedDateTime dt = doc['updated'].value; int year = dt.getYear(); int month = dt.getMonthValue(); int day = dt.getDayOfMonth(); return Long.parseLong(String.format("%04d%02d%02d", year, month, day)); """ }, "order": "desc" } } ], "script_fields": { "updated_yyyyMMdd": { "script": { "lang": "painless", "source": """ ZonedDateTime dt = doc['updated'].value; int year = dt.getYear(); int month = dt.getMonthValue(); int day = dt.getDayOfMonth(); return Long.parseLong(String.format("%04d%02d%02d", year, month, day)); """ } } }, "_source": ["updated"] }
关键注意点
- 补零处理:用
%02d格式化月份和日期,确保1月变成01、4日变成04,避免出现202014这种错误格式。 - 数字类型选择:用
Long.parseLong转成Long类型,比Int更稳妥(虽然8位数字在Int范围内,但Long兼容性更好)。 - 日期API:Elasticsearch的Painless中,
doc['updated'].value是ZonedDateTime类型,推荐用getMonthValue()获取月份(旧的getMonthOfYear()已逐步废弃)。
内容的提问来源于stack exchange,提问作者user379151
相关产品推荐
相关产品推荐

