给定
private Map<String, ZonedDateTime> timePoints = new HashMap<>();
如何提示春季数据字段的类型?
当直接放在字典上时,转换器会尝试将键和值一起解析,如果它们是日期字符串的话。
@Field(FieldType.Date)
private Map<String, ZonedDateTime> timePoints = new HashMap<>();
当没有提供字段类型时,会出现以下错误:
Type .. of property .. is a TemporalAccessor class but has neither a @Field annotation defining the date type nor a registered converter for writing! It will be mapped to a complex object in Elasticsearch!
从文档中,您可能需要创建自定义转换器,并将它们添加到自定义ElasticsearchCustomConversions
bean中。以下转换器似乎可以工作:
@Bean
public ElasticsearchCustomConversions elasticsearchCustomConversions() {
return new ElasticsearchCustomConversions(
Arrays.asList(new ZonedDateTimeWriteConverter(), new ZonedDateTimeReadConverter()));
}
@WritingConverter
static class ZonedDateTimeWriteConverter implements Converter<ZonedDateTime, String> {
@Override
public String convert(ZonedDateTime source) {
return DateTimeFormatter.ISO_ZONED_DATE_TIME.format(source);
}
}
@ReadingConverter
static class ZonedDateTimeReadConverter implements Converter<String, ZonedDateTime> {
@Override
public ZonedDateTime convert(String source) {
return ZonedDateTime.from(DateTimeFormatter.ISO_ZONED_DATE_TIME.parse(source));
}
}
像一样在属性上放置注释
@Field(FieldType.Date)
private Map<String, ZonedDateTime> timePoints = new HashMap<>();
无法工作,因为Map
不是临时类型,因此无法转换为临时类型。
如果保留注释,则Map<String, ZonedDateTime>
将被解释为对象。例如,如果你有
Map<String, ZonedDateTime> map = new Map();
map.put("utc", ZonedDateTime.of(LocalDateTime.now(), ZoneId.of("UTC")));
map.put("paris", ZonedDateTime.of(LocalDateTime.now(), ZoneId.of("Europe/Paris")));
然后在用Spring Data Elasticsearch存储这个对象时,它将尝试创建一个要发送到Elasticsearch(JSON表示)的对象,如下所示:
{
"utc": {
},
"paris": {
}
}
应该表示时态的内部对象存储为嵌套对象,而不是某个转换值,因为无法将字段类型添加到映射的值中-您可以在日志中看到有关的警告。
但是在Elasticsearch中使用Map
作为属性无论如何都是有问题的。键被解释为子对象的属性。之前不可能在索引中定义类型的映射,因为不知道这些属性可以有什么可能的名称。在我的例子中;utc";以及";巴黎";,但它可以是任何字符串。每一个值将由Elasticsearch作为动态映射字段添加到索引中。这可能会导致所谓的映射爆炸,因此Elasticsearch将索引中的字段数限制为默认值1000。您可以重新考虑在Elasticsearch中存储数据的方式。
如果你想坚持使用Map
,你需要编写一个自定义转换器,能够将你的Map<String, ZonedDateTime>
转换为Map<String, String>
并返回。
不知道我是否100%理解您的问题,但您应该尝试实现Persistable并添加带注释的属性,这些值将自动为存储在Elasticsearch中的实体维护,例如:
@Document(indexName = "person")
public class Person implements Persistable<Long> {
@Nullable @Id
private Long id;
@CreatedDate
@Nullable @Field(type = FieldType.Date, format = DateFormat.basic_date_time)
private Instant created;
@Nullable @CreatedBy
private String createdBy;
@LastModifiedDate
@Nullable @Field(type = FieldType.Date, format = DateFormat.basic_date_time)
private Instant lastModified;
@Nullable @LastModifiedBy
private String lastModifiedBy;
@Nullable
public Long getId() { return id; }
@Override
public boolean isNew() { return id == null || (createdBy == null && created == null); }
// other properties, getter, setter...
}