elasticsearch,spring-data,Java,Spring,elasticsearch,Spring Data" /> elasticsearch,spring-data,Java,Spring,elasticsearch,Spring Data" />

如何使Spring数据Elasticsearch与日期的java.time.LocalDateTime一起工作

如何使Spring数据Elasticsearch与日期的java.time.LocalDateTime一起工作,java,spring,elasticsearch,spring-data,Java,Spring,elasticsearch,Spring Data,我使用Spring数据支持Elasticsearch。以下是时间戳字段映射: @Field(type = FieldType.Date, index = FieldIndex.not_analyzed, store = true, format = DateFormat.custom, pattern = "yyyy-MM-dd'T'HH:mm:ss.SSSZZ") @JsonFormat(shape = JsonFormat.Shape.STRING, pattern ="yy

我使用Spring数据支持Elasticsearch。以下是时间戳字段映射:

@Field(type = FieldType.Date, index = FieldIndex.not_analyzed, store = true,
        format = DateFormat.custom, pattern = "yyyy-MM-dd'T'HH:mm:ss.SSSZZ")
@JsonFormat(shape = JsonFormat.Shape.STRING, pattern ="yyyy-MM-dd'T'HH:mm:ss.SSSZZ")
private LocalDateTime timestamp;
这将导致Elasticsearch中的字段映射如下:

"timestamp":{"type":"date","store":true,"format":"yyyy-MM-dd'T'HH:mm:ss.SSSZZ"}
当我使用java.util.Date时,一切正常。但是,当我切换到上面提到的java.time.LocalDateTime时,发送到Elasticsearch的文档会导致异常。以下是文档(仅为简洁起见,时间戳字段):

例外情况是:

MapperParsingException[failed to parse [timestamp]]; nested: IllegalArgumentException[unknown property [hour]];
(...)
Caused by: java.lang.IllegalArgumentException: unknown property [hour]
在jsoning文档时,这里似乎忽略了该模式。有什么建议吗?或者您可能知道如何将“内置”时间戳字段与Spring数据一起使用?

检查以将
JavaTimeModule
添加到
ObjectMapper

@Configuration
public class ElasticSearchConfiguration {

  @Bean
  public ElasticsearchTemplate elasticsearchTemplate(Client client) {
    return new ElasticsearchTemplate(client, new CustomEntityMapper());
  }

  public static class CustomEntityMapper implements EntityMapper {

    private final ObjectMapper objectMapper;

    public CustomEntityMapper() {
      objectMapper = new ObjectMapper();
      objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
      objectMapper.configure(DeserializationFeature.ACCEPT_SINGLE_VALUE_AS_ARRAY, true);
      objectMapper.registerModule(new CustomGeoModule());
      objectMapper.registerModule(new JavaTimeModule());
    }

    @Override
    public String mapToString(Object object) throws IOException {
      return objectMapper.writeValueAsString(object);
    }

    @Override
    public <T> T mapToObject(String source, Class<T> clazz) throws IOException {
      return objectMapper.readValue(source, clazz);
    }
  }
}
@配置
公共类ElasticSearchConfiguration{
@豆子
公共ElasticsearchTemplate ElasticsearchTemplate(客户端){
返回新的ElasticsearchTemplate(客户端,新CustomEntityMapper());
}
公共静态类CustomEntityMapper实现EntityMapper{
私有最终ObjectMapper ObjectMapper;
公共客户标签(){
objectMapper=新的objectMapper();
objectMapper.configure(在未知属性上反序列化feature.FAIL,false);
configure(反序列化功能。接受单个值作为数组,true);
registerModule(新的CustomGemoModule());
registerModule(新的JavaTimeModule());
}
@凌驾
公共字符串mapToString(对象对象)引发IOException{
返回objectMapper.writeValueAsString(对象);
}
@凌驾
公共T mapToObject(字符串源,类clazz)引发IOException{
返回objectMapper.readValue(源,clazz);
}
}
}

我遇到了类似的问题:日期值中的“Z”被视为字符,因此日期解析失败。我的解决方案是使用自定义模式来确保转换正确:

@Field(type = FieldType.Date, format = DateFormat.custom, pattern = "yyyy-MM-dd'T'HH:mm:ss'Z'")
private LocalDateTime dateField;
如果我们不想在不同的字段上重复这个模式,我们可以尝试集中到转换逻辑。Spring数据弹性搜索提供了自定义转换功能,请查看示例


基本上,我们可以编写一个从字符串到LocalDateTime的转换器,并将日期模式放在那里。

这看起来很有希望。DefaultModule不使用JavaTimeModule的原因可能是为了支持JDK<8。。。您可以使用
objectMapper.findAndRegisterModules()
注册类路径中的所有模块…这是Spring Data已经提供的最佳解决方案。
@Field(type = FieldType.Date, format = DateFormat.custom, pattern = "yyyy-MM-dd'T'HH:mm:ss'Z'")
private LocalDateTime dateField;