使用Spring Data Elasticsearch定义自定义日期格式和转换器 [英] Define a custom date format and converter with Spring Data Elasticsearch

查看:336
本文介绍了使用Spring Data Elasticsearch定义自定义日期格式和转换器的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I'm currently migrating from Spring Data Elasticsearch 3.2.x to 4.0.0.

我要删除定义了自定义 ZonedDateTimeDeserializer JacksonEntityMapper ,以使用 ElasticsearchEntityMapper

I'm removing a JacksonEntityMapper, that defined a custom ZonedDateTimeDeserializer, to use the ElasticsearchEntityMapper

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

I have a ZonedDateTime field defined as follows:

    @Field(type = Date, format = DateFormat.date_time)
    private final ZonedDateTime loggedIn;

但是,反序列化会丢失区域信息,因此存储之前和之后的字段之间的比较将失败:

However, the deserialization of this loses the zone information, so that a comparison between the field before and after being stored fails:

之前

loggedIn=2020-06-01T09:50:27.389589+01:00[Europe/London]

之后

loggedIn=2020-06-01T09:50:27.389+01:00

我希望仅存储时区偏移量,所以会丢失区域信息.借助Jackson的 ZonedDateTimeDeserializer ,我能够在ZonedDateTime构建期间应用区域.

I expect the zone information to be lost as only the timezone offset is being stored. With the Jackson ZonedDateTimeDeserializer I was able to apply the Zone during the ZonedDateTime construction.

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

Ideally, I'd like to define a custom date format and converter classes to handle my scenario.

我尝试了以下字段配置:

I've tried the following field configuration:

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

带有Reading/WritingConverters

With Reading/WritingConverters

@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()));
    }
}

和配置

public class ElasticConfiguration extends AbstractElasticsearchConfiguration {

    @Bean
    @Override
    public ElasticsearchCustomConversions elasticsearchCustomConversions() {
        return new ElasticsearchCustomConversions(List.of(new ZonedDateTimeToStringConverter(),
                                                          new StringToZonedDateTimeConverter()));
    }
}

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

However, the reading of the field fails with an exception

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)
    ...

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

Looking at the exception, when comparing the parsing against the successful DateFormat.date_time read, I may have an error in the pattern. The TemporalAccessor for the DateFormat.date_time is {OffsetSeconds=3600, InstantSeconds=1597918271},ISO resolved to 2020-08-20T11:11:11.123, whereas my custom pattern parses to {YearOfEra=2020, MonthOfYear=8, DayOfMonth=20, OffsetSeconds=3600},ISO resolved to 11:11:11.123

但是似乎我指定的自定义转换器也没有被使用.笔记.我指定了其他正在接受的客户转换器,所以请不要相信这是配置问题.

But it also seems that the custom converters I specified aren't being picked up. Note. I have other customer converters specified that are being picked up so don't believe it's a configuration issue.

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

Any help would be appreciated, I'm not sure why the custom pattern fails, but think I could avoid it if the custom converters were picked up. I can workaround the issue for now, but ideally I'd like everything to be consistent before and after the upgrade.

推荐答案

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

Don't use yyyy in a date pattern, change it to (see the Elasticsearch docs)

pattern = "uuuu-MM-dd'T'HH:mm:ss.SSSSSSZ")

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

By defining the property as FieldType.Dateinternally a converter is created for this property and used; the custom converters aren't needed

这篇关于使用Spring Data Elasticsearch定义自定义日期格式和转换器的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆