【问题标题】:ElasticSearch Spring-Data Date format always is longElasticSearch Spring-Data 日期格式总是很长
【发布时间】:2015-11-09 14:53:21
【问题描述】:

当使用spring-data插入Date类型的Elasticsearch文档时,我无法得到正确的日期格式,日期格式总是Long。

这里是java代码:Entity.java

import java.util.Date;

import org.springframework.data.annotation.Id;
import org.springframework.data.elasticsearch.annotations.DateFormat;
import org.springframework.data.elasticsearch.annotations.Document;
import org.springframework.data.elasticsearch.annotations.Field;
import org.springframework.data.elasticsearch.annotations.FieldIndex;
import org.springframework.data.elasticsearch.annotations.FieldType;

import com.fasterxml.jackson.annotation.JsonProperty;

@Document(indexName = "entity-index", type = "entity-type")
public class Entity {
    @Id
    private String id;

    @Field(type = FieldType.Date, index = FieldIndex.not_analyzed, store = true, 
            format = DateFormat.custom, pattern = "yyyy-MM-dd'T'hh:mm:ss.SSS'Z'")
    private Date createDate;

    private String system;
    private double score;

    @Field(type = FieldType.Date, format = DateFormat.date_optional_time)
    @JsonProperty(value = "@timestamp")
    private Date updateDate;
    // omit setter and getter 
}

这是测试

public class EntityDAOTest {
    @Autowired
    private ElasticsearchTemplate template;

    @Before
    public void init() {
        template.createIndex(Entity.class);
        template.putMapping(Entity.class);
    }


    @Test
    public void testCreate() {
        Entity entity = new Entity();
        entity.setId("5");
        entity.setCreateDate(new DateTime(2015,05,27,0,0).toDate());
        entity.setUpdateDate(new DateTime(2015,05,27,0,0).toDate());
        entity.setSystem("systemC");
        entity.setScore(5.7);
        IndexQuery query = new IndexQueryBuilder().withObject(entity).withId(entity.getId()).build();
        template.index(query);
    }

我可以得到创建实体的映射:

{
   "entity-index": {
      "mappings": {
         "entity-type": {
            "properties": {
               "@timestamp": {
                  "type": "long"
               },
               "createDate": {
                  "type": "date",
                  "store": true,
                  "format": "yyyy-MM-dd'T'hh:mm:ss.SSS'Z'"
               },
               "id": {
                  "type": "string"
               },
               "score": {
                  "type": "double"
               },
               "system": {
                  "type": "string"
               },
               "updateDate": {
                  "type": "date",
                  "format": "date_optional_time"
               }
            }
         }
      }
   }
}

但是,当我搜索 curl -X GET /entity-index/_search 时,我得到以下文档:

 {
               "id": "5",
               "createDate": 1432656000000,
               "system": "systemC",
               "score": 5.7,
               "@timestamp": 1432656000000
 }

而且日期字段都是Long类型,我怎样才能得到日期格式:'2015-08-17T12:00:00.000'?

【问题讨论】:

  • 请尝试使用正确的日期格式yyyy-MM-dd'T'HH:mm:ss.SSSZZ,即小时必须大写并且Z 时区和Z 周围的刻度不得加倍。您也可以简单地使用date_time 格式。请注意,您需要先清除索引才能测试此更改。
  • 感谢您的回答,我尝试了您的建议,删除索引,更改模式,但仍然显示为时间戳
  • 实际上,您的映射已正确创建。问题更有可能来自 Jackson JSON 序列化程序。您应该尝试将此注释添加到您的日期字段:@JsonFormat (shape = JsonFormat.Shape.STRING, pattern ="yyyy-MM-dd'T'HH:mm:ss.SSSZZ")。另请参阅一些可能更适合您的情况的 alternative solutions
  • 是的,你是对的,将代码更改为:@JsonFormat (shape = JsonFormat.Shape.STRING, pattern ="yyyy-MM-dd'T'HH:mm:ss.SSS' Z'") @JsonProperty(value = "@timestamp") 私有日期 updateDate;问题解决了

标签: java spring elasticsearch


【解决方案1】:

您的映射已正确创建。问题更有可能来自 Jackson JSON 序列化程序。您应该尝试将此注释添加到您的日期字段:@JsonFormat (shape = JsonFormat.Shape.STRING, pattern ="yyyy-MM-dd'T'HH:mm:ss.SSSZZ")

还有一些alternative solutions 可能更适合您的情况(即创建CustomDateSerializer 等)。

【讨论】:

  • 我在日期字段上使用@JsonFormat (shape = JsonFormat.Shape.STRING, pattern ="yyyy-MM-dd'T'HH:mm:ss.SSSZZ"),但它仍然失败原因:org.elasticsearch.index.mapper.MapperParsingException:解析失败 [creationDate]- 原因:java.lang.NumberFormatException:对于输入字符串:“2018-04-04T14:19:49”。有什么选择吗?
  • @PetrKostroun 您错过了时区,请从模式中删除 ZZ
  • @Val 我正在使用 Spring Boot 和使用 Jhipster 开发的 elasticsearch jpa。
  • @Column(name = "created_date", columnDefinition = "Instant.now()") private Instant createdDate = Instant.now();公共文档 createdDate(Instant createdDate) { this.createdDate = createdDate;返回这个; }
  • 以上代码生成,索引列类型为long。因此,当我添加数据时,它存储的值如下:1588938113466。但是在检索时它会给出异常,例如,无法解析 [long] 类型的字段 [createdDate]
【解决方案2】:

Starting from Elasticsearch 7 你不应该使用yyyy 而应该使用uuuu。例如:

@Field(type = FieldType.Date, format = DateFormat.custom, pattern = "uuuu-MM-dd'T'HH:mm:ss.SSSZZ")
private Date lastModifiedDate;

您不需要@JsonProperty,因为现在 Spring Data Elasticsearch 不使用 Jackson,而是使用 MappingElasticsearchConverter。有了这个注解,就会自动为这个属性创建一个转换器并使用它。

【讨论】:

    【解决方案3】:

    如果满足需要,我建议尝试现有的可用映射。 使用 es 版本:7.14.1,以下效果很好:

    @Field(type = FieldType.Date, format = DateFormat.basic_date_time)
    private Date creationTime;
    

    好处是不必担心映射,因为它是自动创建的。旧版本可能支持它,我没有检查过。

    【讨论】:

    • 希望人们仔细阅读这一点,因为这是更好的方法,应该是公认的答案。
    • 我还要补充一点,DateFormat.date_time 提供的格式比 DateFormat.basic_date_time 更易于阅读。
    【解决方案4】:

    以下设置对我有用。 注意:在测试此更改之前删除您的索引。确保所有地方的模式都相同。

    @Field(type = FieldType.Date, store = true, format = DateFormat.custom, pattern = "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'")
    @JsonFormat (shape = JsonFormat.Shape.STRING, pattern ="yyyy-MM-dd'T'HH:mm:ss.SSS'Z'")
    private Date date;
    

    【讨论】:

    • 我们必须在FieldJsonFormat 中复制注释值真的很奇怪。
    • 对我来说,只添加@JsonFormat注解就足够了
    【解决方案5】:

    注意事项:

    JSON 没有日期数据类型,因此 Elasticsearch 中的日期可以 要么是:

    • 包含格式化日期的字符串,例如“2015-01-01”或“2015/01/01. 12:10:30”。
    • 一个长整数,表示自时代以来的毫秒数。
    • 一个整数,表示自纪元以来的秒数。

    也来自同一个文档:

    日期将始终呈现为字符串,即使它们最初是 在 JSON 文档中以 long 形式提供

    这意味着查询日期字段的数据类型将始终是字符串、长整数或整数。弹性搜索中没有特殊的“日期”字段。

    在此处阅读更多信息:https://www.elastic.co/guide/en/elasticsearch/reference/current/date.html

    【讨论】:

      猜你喜欢
      • 2016-05-10
      • 2022-01-06
      • 1970-01-01
      • 2021-03-03
      • 1970-01-01
      • 2018-10-13
      • 2019-11-09
      • 2016-12-11
      • 2021-09-13
      相关资源
      最近更新 更多