使用 Spring Data Elasticsearch 定义自定义日期格式和转换器

Mat*_*ner 2 java elasticsearch spring-data-elasticsearch

我目前正在从 Spring Data Elasticsearch 3.2.x 迁移到 4.0.0。

我正在删除JacksonEntityMapper定义了自定义的ZonedDateTimeDeserializer,以使用ElasticsearchEntityMapper

我有一个 ZonedDateTime 字段定义如下:

    @Field(type = Date, format = DateFormat.date_time)
    private final ZonedDateTime loggedIn;
Run Code Online (Sandbox Code Playgroud)

但是,this的反序列化丢失了zone信息,从而导致存储前后字段的比较失败:

loggedIn=2020-06-01T09:50:27.389589+01:00[Europe/London]
Run Code Online (Sandbox Code Playgroud)

loggedIn=2020-06-01T09:50:27.389+01:00
Run Code Online (Sandbox Code Playgroud)

我希望区域信息会丢失,因为只存储了时区偏移量。使用 Jackson,ZonedDateTimeDeserializer我能够在 ZonedDateTime 构建期间应用 Zone。

理想情况下,我想定义一个自定义日期格式和转换器类来处理我的场景。

我尝试了以下字段配置:

    @Field(type = Date, format = DateFormat.custom, pattern = "yyyy-MM-dd'T'HH:mm:ss.SSSSSSZ")
    private final ZonedDateTime loggedIn;
Run Code Online (Sandbox Code Playgroud)

使用读/写转换器

@WritingConverter
public class ZonedDateTimeToStringConverter implements Converter<ZonedDateTime, String>  {

    @Override
    public String convert(ZonedDateTime source) {
        return source.format(DateTimeFormatter.ISO_OFFSET_DATE_TIME);
    }
}

@ReadingConverter
public class StringToZonedDateTimeConverter implements Converter<String, ZonedDateTime>  {

    @Override
    public ZonedDateTime convert(String source) {
        return ZonedDateTime.parse(source, DateTimeFormatter.ISO_OFFSET_DATE_TIME.withZone(ZoneId.systemDefault()));
    }
}
Run Code Online (Sandbox Code Playgroud)

和配置

public class ElasticConfiguration extends AbstractElasticsearchConfiguration {

    @Bean
    @Override
    public ElasticsearchCustomConversions elasticsearchCustomConversions() {
        return new ElasticsearchCustomConversions(List.of(new ZonedDateTimeToStringConverter(),
                                                          new StringToZonedDateTimeConverter()));
    }
}
Run Code Online (Sandbox Code Playgroud)

但是,该字段的读取失败,但有异常

Caused by: java.time.DateTimeException: Unable to obtain LocalDate from TemporalAccessor: {YearOfEra=2020, MonthOfYear=8, DayOfMonth=20, OffsetSeconds=3600},ISO resolved to 11:11:11.123 of type java.time.format.Parsed
    at java.base/java.time.LocalDate.from(LocalDate.java:396)
    at java.base/java.time.ZonedDateTime.from(ZonedDateTime.java:560)
    at org.springframework.data.elasticsearch.core.convert.ElasticsearchDateConverter.parse(ElasticsearchDateConverter.java:109)
    at org.springframework.data.elasticsearch.core.convert.ElasticsearchDateConverter.parse(ElasticsearchDateConverter.java:114)
    ...
Run Code Online (Sandbox Code Playgroud)

查看异常,将解析与成功DateFormat.date_time读取进行比较时,我可能在模式中有错误。DateFormat.date_timeis的 TemporalAccessor {OffsetSeconds=3600, InstantSeconds=1597918271},ISO resolved to 2020-08-20T11:11:11.123,而我的自定义模式解析为{YearOfEra=2020, MonthOfYear=8, DayOfMonth=20, OffsetSeconds=3600},ISO resolved to 11:11:11.123

但我指定的自定义转换器似乎也没有被选中。笔记。我有其他指定的客户转换器正在被接受,所以不要相信这是一个配置问题。

任何帮助将不胜感激,我不确定为什么自定义模式失败,但我认为如果选择了自定义转换器,我可以避免它。我现在可以解决这个问题,但理想情况下,我希望升级前后的一切都保持一致。

P.J*_*sch 7

不要在日期模式中使用yyyy,将其更改为(请参阅Elasticsearch 文档

pattern = "uuuu-MM-dd'T'HH:mm:ss.SSSSSSZ")
Run Code Online (Sandbox Code Playgroud)

通过在FieldType.Date内部定义属性,为此属性创建并使用转换器;不需要自定义转换器