Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

ElasticSearch Spring-Data Date format always is long

When using spring-data to insert Elasticsearch document with Date type, I can't get right date format, the date format always is Long.

here is the java code: 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 
}

Here is the Test

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

I can get the mapping of the created entity:

{
   "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"
               }
            }
         }
      }
   }
}

However, when I search it curl -X GET /entity-index/_search, I get the following document:

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

and the Date Fields are all Long type, how can I get the date format : '2015-08-17T12:00:00.000'?

like image 697
fudy Avatar asked Aug 17 '15 03:08

fudy


People also ask

What is Epoch_millis?

It is the UNIX epoch time, in milliseconds. It is the number of seconds that have elapsed since 00:00:00 Thursday, 1 January 1970 till today.

Does spring data support Elasticsearch?

The Spring Data Elasticsearch project provides integration with the Elasticsearch search engine. Key functional areas of Spring Data Elasticsearch are a POJO centric model for interacting with a Elastichsearch Documents and easily writing a Repository style data access layer.


5 Answers

Your mapping is created correctly. The problem is more likely to come from the Jackson JSON serializer. You should try adding this annotation to your date fields: @JsonFormat (shape = JsonFormat.Shape.STRING, pattern ="yyyy-MM-dd'T'HH:mm:ss.SSSZZ").

There are also some alternative solutions that might better suit your case (i.e. creating a CustomDateSerializer, etc).

like image 73
Val Avatar answered Oct 06 '22 18:10

Val


I would suggest to give a try to existing mappings available if they suffice the need. With es version: 7.14.1, following works quite well:

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

Good thing is one doesn't have to worry about mappings, as it's automatically created. It might be supported in older versions, which I haven't checked.

like image 30
Harish Kumar Saini Avatar answered Oct 06 '22 16:10

Harish Kumar Saini


Starting from Elasticsearch 7 you should't use yyyy but uuuu. e.g:

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

You don't need @JsonProperty because now Spring Data Elasticsearch doesn't use Jackson but instead a MappingElasticsearchConverter. With this annotation, a converter is automatically created for this property and used.

like image 40
GiovanyMoreno Avatar answered Oct 06 '22 17:10

GiovanyMoreno


It worked for me with below settings. Note: delete your index before to test this change. Make sure that the patterns are same at all places.

@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;
like image 34
Wilson Paul Avatar answered Oct 06 '22 17:10

Wilson Paul


Something to keep in mind:

JSON doesn’t have a date data type, so dates in Elasticsearch can either be:

  • Strings containing formatted dates, e.g. "2015-01-01" or "2015/01/01. 12:10:30".
  • A long number representing milliseconds-since-the-epoch.
  • An integer representing seconds-since-the-epoch.

Also from the same doc:

Dates will always be rendered as strings, even if they were initially supplied as a long in the JSON document

This implies that querying the data type for a date field will always be a string, a long or an integer. There is no special "Date" field in elastic search.

Read more here: https://www.elastic.co/guide/en/elasticsearch/reference/current/date.html

like image 24
Skillz Avatar answered Oct 06 '22 16:10

Skillz