Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Spring Data Elasticsearch : @Field and non @Field all got indexed

I chose to use my @Entity class to be marked with @Document as well, so that saving the overhead of maintaining the DTOs.

Now, when trying to index into elasticsearch these entities, they got stored into elastic with all properties (Unless i explicitly mark those unwanted with @JsonIgnore).

Could anyone just explain to me what really happens, and if it is possible to just selectively chose specific properties.

Note : marking some of them a @Field does not make any difference

like image 886
Ahmad Khundaqji Avatar asked Aug 14 '15 00:08

Ahmad Khundaqji


3 Answers

I found a workaround that might be helpful for some.

1. Create a Custom EntityMapper EntityMapper is an interface that comes with the spring data elasticsearch package org.springframework.data.elasticsearch.core, this interface has one implementation class by default called DefaultEntityMapper with two methods to override.

public String mapToString(Object object) throws IOException;

SimpleFilterProvider filters = new SimpleFilterProvider();
filters.setDefaultFilter(SimpleBeanPropertyFilter.filterOutAllExcept(fieldsNotToFilter));
filters.setFailOnUnknownId(false);
String dtoAsString = objectMapper.writer(filters).writeValueAsString(object);

Note that you need @JsonFilter("filterName") annotation to mark the entity class.

2. Inject the created CustomEntityMapper into elasticsearch:transport-client bean name="entityMapper" class="com.modym.core.search.CustomEntityMapper

like image 96
Ahmad Khundaqji Avatar answered Oct 17 '22 22:10

Ahmad Khundaqji


You are right, also fields without @Field are included. But:

  1. They are NOT indexed and not present in the mapping
  2. Spring data (a not so mature and so valuable project) Jsonizes all fields by default, so the problem is Spring Data as you are saying, but instead of your complex solution you can do add this annotation to your entity: @Document( indexName = INDEX_NAME, type = TYPE, shards = 1, replicas = 0 ) @JsonIgnoreProperties( value = {"field1", "field2", ..., "fieldN"} ) public class Entity {
like image 22
andPat Avatar answered Oct 18 '22 00:10

andPat


See Field description in: https://docs.spring.io/spring-data/elasticsearch/docs/3.2.4.RELEASE/reference/html/#elasticsearch.mapping.meta-model.annotations It states:

@Field: Applied at the field level and defines properties of the field, most of the attributes map to the respective Elasticsearch Mapping definitions

I.e. @Field annotation defines field properties, not its presence in a mapping.

If you don't want to map a variable you have (at least) two options:

  1. Use @JsonIgnore annotation
  2. Use @Mapping for importing your mapping file. In the mapping file, disable Dynamic Mapping - https://www.elastic.co/guide/en/elasticsearch/guide/current/dynamic-mapping.html
like image 2
Josef Veselý Avatar answered Oct 18 '22 00:10

Josef Veselý