Spring Data Elasticsearch Repository查询定义日期输入参数格式
Spring Data Elasticsearch Repository query define date input parameter format
我正在使用 elasticsearch 6.5.3 和 Spring Boot 2.1.6 和 spring-data-elasticsearch 3.2.0.M1。
我将 Elasticsearch 配置定义为:
@Bean
public ElasticsearchOperations elasticsearchTemplate() {
return new ElasticsearchRestTemplate(client(), new CustomEntityMapper());
}
public static class CustomEntityMapper implements EntityMapper {
private final ObjectMapper objectMapper;
public CustomEntityMapper() {
//we use this so that Elasticsearch understands LocalDate and LocalDateTime objects
objectMapper = new ObjectMapper()
.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES)
.enable(DeserializationFeature.ACCEPT_SINGLE_VALUE_AS_ARRAY)
.disable(DeserializationFeature.READ_DATE_TIMESTAMPS_AS_NANOSECONDS)
.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS)
//MUST be registered BEFORE calling findAndRegisterModules
.registerModule(new JavaTimeModule())
.registerModule(new Jdk8Module());
//only autodetect fields and ignore getters and setters for nonexistent fields when serializing/deserializing
objectMapper.setVisibility(objectMapper.getSerializationConfig().getDefaultVisibilityChecker()
.withFieldVisibility(JsonAutoDetect.Visibility.ANY)
.withGetterVisibility(JsonAutoDetect.Visibility.NONE)
.withSetterVisibility(JsonAutoDetect.Visibility.NONE)
.withCreatorVisibility(JsonAutoDetect.Visibility.NONE));
//load the other available modules as well
objectMapper.findAndRegisterModules();
}
@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);
}
}
我有一个存储库,其方法定义为:
List<AccountDateRollSchedule> findAllByNextRollDateTimeLessThanEqual(final LocalDateTime dateTime);
POJO AccountDateRollSchedule 将该字段定义为:
@Field(type = FieldType.Date, format = DateFormat.date_hour_minute)
@DateTimeFormat(pattern = "yyyy-MM-dd'T'HH:mm")
@JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd'T'HH:mm")
private LocalDateTime nextRollDateTime;
我看到我的索引正确地创建了声明和预期的字段:
"nextRollDateTime": {
"type": "date",
"format": "date_hour_minute"
}
同时查询索引 returns 字段格式如预期:
"nextRollDateTime" : "2019-06-27T13:34"
我的存储库查询将转换为:
{"query":
{"bool" :
{"must" :
{"range" :
{"nextRollDateTime" :
{"from" : null,
"to" : "?0",
"include_lower" : true,
"include_upper" : true
}
}
}
}
}
}
但是将任何 LocalDateTime 输入传递给该方法并不遵循为该字段定义的格式,而是始终使用 FULL 格式。正在调用:
findAllByNextRollDateTimeLessThanEqual(LocalDateTime.now(ZoneOffset.UTC).truncatedTo(ChronoUnit.MINUTES));
出现以下异常(忽略存储库中方法参数上的任何 @DateTimeFormat 或 @JsonFormat 注释):
Unrecognized chars at the end of [2019-07-22T09:07:00.000]: [:00.000]
如果我改为更改存储库方法以接受字符串并将格式与输入完全相同的字符串传递给它,则它没有问题。
是否可以以某种方式定义用于输入到存储库方法的日期参数的格式,或者让 Spring 使用在字段本身上配置的格式?
我不想为像这样的简单转换包装该方法(我做了并且有效),我也想避免在日期字段中使用 long 类型
感谢和欢呼
作为参考,我也在 Spring JIRA
上打开了问题
这些问题是我们不再在 Spring Data Elasticsearch 中使用和公开 JacksonMapper 的原因之一。从 4.0 版开始,您的 属性 只需要一个注解:
@Field(type = FieldType.Date, format = DateFormat.date_hour_minute)
private LocalDateTime nextRollDateTime;
这将用于编写索引映射、索引和检索实体时以及处理存储库方法和查询时。
但是对于 3.2.x 版本,您将不得不使用您提到的包装之类的解决方法。
我正在使用 elasticsearch 6.5.3 和 Spring Boot 2.1.6 和 spring-data-elasticsearch 3.2.0.M1。
我将 Elasticsearch 配置定义为:
@Bean
public ElasticsearchOperations elasticsearchTemplate() {
return new ElasticsearchRestTemplate(client(), new CustomEntityMapper());
}
public static class CustomEntityMapper implements EntityMapper {
private final ObjectMapper objectMapper;
public CustomEntityMapper() {
//we use this so that Elasticsearch understands LocalDate and LocalDateTime objects
objectMapper = new ObjectMapper()
.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES)
.enable(DeserializationFeature.ACCEPT_SINGLE_VALUE_AS_ARRAY)
.disable(DeserializationFeature.READ_DATE_TIMESTAMPS_AS_NANOSECONDS)
.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS)
//MUST be registered BEFORE calling findAndRegisterModules
.registerModule(new JavaTimeModule())
.registerModule(new Jdk8Module());
//only autodetect fields and ignore getters and setters for nonexistent fields when serializing/deserializing
objectMapper.setVisibility(objectMapper.getSerializationConfig().getDefaultVisibilityChecker()
.withFieldVisibility(JsonAutoDetect.Visibility.ANY)
.withGetterVisibility(JsonAutoDetect.Visibility.NONE)
.withSetterVisibility(JsonAutoDetect.Visibility.NONE)
.withCreatorVisibility(JsonAutoDetect.Visibility.NONE));
//load the other available modules as well
objectMapper.findAndRegisterModules();
}
@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);
}
}
我有一个存储库,其方法定义为:
List<AccountDateRollSchedule> findAllByNextRollDateTimeLessThanEqual(final LocalDateTime dateTime);
POJO AccountDateRollSchedule 将该字段定义为:
@Field(type = FieldType.Date, format = DateFormat.date_hour_minute)
@DateTimeFormat(pattern = "yyyy-MM-dd'T'HH:mm")
@JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd'T'HH:mm")
private LocalDateTime nextRollDateTime;
我看到我的索引正确地创建了声明和预期的字段:
"nextRollDateTime": {
"type": "date",
"format": "date_hour_minute"
}
同时查询索引 returns 字段格式如预期:
"nextRollDateTime" : "2019-06-27T13:34"
我的存储库查询将转换为:
{"query":
{"bool" :
{"must" :
{"range" :
{"nextRollDateTime" :
{"from" : null,
"to" : "?0",
"include_lower" : true,
"include_upper" : true
}
}
}
}
}
}
但是将任何 LocalDateTime 输入传递给该方法并不遵循为该字段定义的格式,而是始终使用 FULL 格式。正在调用:
findAllByNextRollDateTimeLessThanEqual(LocalDateTime.now(ZoneOffset.UTC).truncatedTo(ChronoUnit.MINUTES));
出现以下异常(忽略存储库中方法参数上的任何 @DateTimeFormat 或 @JsonFormat 注释):
Unrecognized chars at the end of [2019-07-22T09:07:00.000]: [:00.000]
如果我改为更改存储库方法以接受字符串并将格式与输入完全相同的字符串传递给它,则它没有问题。
是否可以以某种方式定义用于输入到存储库方法的日期参数的格式,或者让 Spring 使用在字段本身上配置的格式?
我不想为像这样的简单转换包装该方法(我做了并且有效),我也想避免在日期字段中使用 long 类型
感谢和欢呼
作为参考,我也在 Spring JIRA
上打开了问题这些问题是我们不再在 Spring Data Elasticsearch 中使用和公开 JacksonMapper 的原因之一。从 4.0 版开始,您的 属性 只需要一个注解:
@Field(type = FieldType.Date, format = DateFormat.date_hour_minute)
private LocalDateTime nextRollDateTime;
这将用于编写索引映射、索引和检索实体时以及处理存储库方法和查询时。
但是对于 3.2.x 版本,您将不得不使用您提到的包装之类的解决方法。