Elasticsearch 6.2.3日期字段解析失败求助(Java API查询场景)
解决Elasticsearch日期查询的解析错误问题
我来帮你搞定这个Elasticsearch日期查询的报错问题!你遇到的[Mon Apr 16 11:56:43 EDT 2018] with format [strict_date_optional_time||epoch_millis]错误,核心原因很明确:Elasticsearch无法解析你传入的日期格式。
错误原因拆解
从你的映射配置来看,目标日期字段指定的格式是strict_date_optional_time或者epoch_millis:
strict_date_optional_time要求日期符合ISO标准格式,比如2018-04-16T11:56:43.000-04:00或者简化的2018-04-16epoch_millis则是毫秒级的时间戳(比如1523882203000)
但你用来作为查询条件的Mon Apr 16 11:56:43 EDT 2018是Java默认的Date.toString()输出格式,不在ES支持的格式列表里,自然会解析失败。
三种可行解决方案
1. 转换日期为ES兼容格式(推荐)
在Java代码里把目标日期转成ES支持的格式,比如用Java 8+的DateTimeFormatter或者旧版的SimpleDateFormat:
Java 8+ 实现代码:
import java.time.ZonedDateTime; import java.time.format.DateTimeFormatter; import java.time.format.DateTimeParseException; public class DateConverter { public static void main(String[] args) { try { // 解析你的原始日期字符串 DateTimeFormatter inputFormatter = DateTimeFormatter.ofPattern("EEE MMM dd HH:mm:ss zzz yyyy"); ZonedDateTime date = ZonedDateTime.parse("Mon Apr 16 11:56:43 EDT 2018", inputFormatter); // 转成ES支持的ISO格式 DateTimeFormatter esFormatter = DateTimeFormatter.ISO_OFFSET_DATE_TIME; String esCompatibleDate = date.format(esFormatter); // 后续用esCompatibleDate作为查询条件即可 System.out.println(esCompatibleDate); // 输出类似:2018-04-16T11:56:43-04:00 } catch (DateTimeParseException e) { e.printStackTrace(); } } }
旧版Java 实现代码:
import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.Date; public class LegacyDateConverter { public static void main(String[] args) { try { SimpleDateFormat inputFormat = new SimpleDateFormat("EEE MMM dd HH:mm:ss zzz yyyy"); Date date = inputFormat.parse("Mon Apr 16 11:56:43 EDT 2018"); // 转成ES支持的格式 SimpleDateFormat esFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSZ"); String esCompatibleDate = esFormat.format(date); // 用于ES查询 System.out.println(esCompatibleDate); // 输出类似:2018-04-16T11:56:43.000-0400 } catch (ParseException e) { e.printStackTrace(); } } }
2. 修改ES映射,添加支持的日期格式
如果你不想改动代码,可以修改目标字段的映射,把你使用的日期格式加入到format列表中。比如:
"your_date_field_name": { "type": "date", "format": "strict_date_optional_time||epoch_millis||EEE MMM dd HH:mm:ss zzz yyyy" }
注意:修改已有索引的映射后,需要重新索引数据,否则旧数据的日期不会被重新解析;另外这种方式会让映射格式变得复杂,长期来看不如保持标准格式更易维护。
3. 使用毫秒级时间戳查询
把你的日期转成毫秒级时间戳(long类型),直接传入ES作为查询条件,这种方式完全不需要担心格式问题:
import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.Date; public class TimestampConverter { public static void main(String[] args) { try { SimpleDateFormat inputFormat = new SimpleDateFormat("EEE MMM dd HH:mm:ss zzz yyyy"); Date date = inputFormat.parse("Mon Apr 16 11:56:43 EDT 2018"); long timestamp = date.getTime(); // 得到毫秒级时间戳 // 直接用timestamp作为查询条件,ES会自动识别为epoch_millis格式 System.out.println(timestamp); // 输出:1523882203000 } catch (ParseException e) { e.printStackTrace(); } } }
总结
优先推荐第一种方案,保持ES日期字段的标准格式能减少后续的格式兼容问题;如果是临时需求或者无法修改代码,可以选择第三种时间戳的方式,最直接高效。
内容的提问来源于stack exchange,提问作者Fastboyz
相关产品推荐
相关产品推荐

