Spring Data Elasticsearch's @Field annotation not working
I could finally replicate and solve the problem. The fact is that I was using ElasticTemplate for indexing and searching docs instead of repositories, because my business logic got a more complicated (use of aggregations, etc.).
After that, I removed the unused OperationDocumentRespository. It seems that the repository is needed for the type mapping being posted to ES server on startup. I thought having the @Document class should be enough, but it isn't.
So we have two options here:
- Keep the OperationDocumentRepository
Add this line to the app startup:
elasticsearchTemplate.putMapping(OperationDocument.class);
I tried to replicate issue using spring data elasticsearch sample application but as per your configuration i am getting the desired results as mentioned above.
Entire code is committed to project here --> link
Look at the TestCase which generate index and apply mapping when spring context loaded--> link
Here is mapping generated by TestCase :
{ "operations" : { "aliases" : { }, "mappings" : { "operation" : { "properties" : { "dateUp" : { "type" : "date", "store" : true, "format" : "dd.MM.yyyy hh:mm" }, "operationName" : { "type" : "string", "store" : true, "analyzer" : "standard" }, "sectors" : { "type" : "nested" }, "someTransientData" : { "type" : "string", "index" : "not_analyzed" } } } }, "settings" : { "index" : { "refresh_interval" : "1s", "number_of_shards" : "5", "store" : { "type" : "fs" }, "creation_date" : "1428677234773", "number_of_replicas" : "1", "version" : { "created" : "1040499" }, "uuid" : "-djzLu-IQ0CBs-M6R0-R6Q" } }, "warmers" : { } }}
Can you create similar example with spring boot using https://github.com/spring-projects/spring-boot/tree/master/spring-boot-samples/spring-boot-sample-data-elasticsearch
and commit on public share?
I encountered this error as well using spring-data-elasticsearch and got a solution. Just put codes below, please check the comments.ES prohibited changing field types after indexes created. However you can change other attributes like fielddata
.
- Spring Data Elasticsearch 3.2.x
- Elasticsearch 6.8.4
- Spring Boot 2.2.x
package com.xxxx.xx.es.entity;import lombok.Builder;import lombok.Data;import lombok.EqualsAndHashCode;import org.springframework.data.annotation.Id;import org.springframework.data.elasticsearch.annotations.Document;import org.springframework.data.elasticsearch.annotations.Field;import org.springframework.data.elasticsearch.annotations.FieldType;import org.springframework.data.elasticsearch.annotations.Mapping;@EqualsAndHashCode(callSuper = true)@Data@Builder@Document(indexName = "gaming-laptop", indexStoreType = "fs")@Mapping(mappingPath = "/gaming-laptop-mappings.json") // use custom json to configure data structure in ES, default spring data won't work although using @Field(type = FieldType.Keyword)public class GamingLaptop extends BaseEntity { @Id private String id; @Field private String cpu; @Field(type = FieldType.Keyword) // this only works in ES 7.6.2+, Spring Data Elasticsearch 4.0.X+ private String brandName; @Field private Integer cores; @Field private Integer threads; @Field private String coreFrequency; @Field private String ssd; @Field private String ram; @Field private String produceDate; @Field private Integer version; @Field private Double price; @Field(type = FieldType.Keyword) private String description;}
resources/gaming-laptop-mappings.json
{ "properties":{ "_class":{ "type":"text", "fields":{ "keyword":{ "type":"keyword", "ignore_above":256 } } }, "brandName":{ "type":"keyword" }, "coreFrequency":{ "type":"text", "fields":{ "keyword":{ "type":"keyword", "ignore_above":256 } } }, "cores":{ "type":"long" }, "cpu":{ "type":"text", "fields":{ "keyword":{ "type":"keyword", "ignore_above":256 } } }, "description":{ "type":"keyword" }, "gmtCreated":{ "type":"text", "fields":{ "keyword":{ "type":"keyword", "ignore_above":256 } } }, "gmtModified":{ "type":"text", "fields":{ "keyword":{ "type":"keyword", "ignore_above":256 } } }, "price":{ "type":"float" }, "produceDate":{ "type":"text", "fields":{ "keyword":{ "type":"keyword", "ignore_above":256 } } }, "ram":{ "type":"text", "fields":{ "keyword":{ "type":"keyword", "ignore_above":256 } } }, "ssd":{ "type":"text", "fields":{ "keyword":{ "type":"keyword", "ignore_above":256 } } }, "threads":{ "type":"long" }, "version":{ "type":"long" } }}
Alternatively you can adapt Javier Alvarez's method by using rest high level client:elasticsearchTemplate.putMapping(OperationDocument.class);