2020-02-21

Spring Elasticsearch Object Mapping

Elasticsearch Object Mapping

Spring Data Elasticsearch allows to choose between two mapping implementations abstracted via the EntityMapper interface:

  • Jackson Object Mapping
  • Meta Model Object Mapping


Jackson Object Mapping

The Jackson2 based approach (used by default) utilizes a customized ObjectMapper instance with spring data specific modules. Extensions to the actual mapping need to be customized via Jackson annotations like @JsonInclude.

@Configuration
public class Config extends AbstractElasticsearchConfiguration { 

  @Override
  public RestHighLevelClient elasticsearchClient() {
    return RestClients.create(ClientConfiguration.create("localhost:9200")).rest();
  }
}

AbstractElasticsearchConfiguration already defines a Jackson2 based entityMapper via ElasticsearchConfigurationSupport.
CustomConversions, @ReadingConverter & @WritingConverter cannot be applied when using the Jackson based EntityMapper.
Setting the name of a mapped field with @Field(name="custom-name") also cannot be used with this Mapper.

Meta Model Object Mapping

The Metamodel based approach uses domain type information for reading/writing from/to Elasticsearch. This allows to register Converter instances for specific domain type mapping.


@Configuration
public class Config extends AbstractElasticsearchConfiguration {

  @Override
  public RestHighLevelClient elasticsearchClient() {
    return RestClients.create(ClientConfiguration.create("localhost:9200")).rest()
  }

  @Bean
  @Override
  public EntityMapper entityMapper() {                                 

    ElasticsearchEntityMapper entityMapper = new ElasticsearchEntityMapper(
      elasticsearchMappingContext(), new DefaultConversionService()    
    );
    entityMapper.setConversions(elasticsearchCustomConversions());     

  return entityMapper;
  }
}

Overwrite the default EntityMapper from ElasticsearchConfigurationSupport and expose it as bean.
Use the provided SimpleElasticsearchMappingContext to avoid inconsistencies and provide a GenericConversionService for Converter registration.
Optionally set CustomConversions if applicable.

Mapping Annotation


The ElasticsearchEntityMapper can use metadata to drive the mapping of objects to documents. The following annotations are available:

@Id: Applied at the field level to mark the field used for identity purpose.

@Document: Applied at the class level to indicate this class is a candidate for mapping to the database. The most important attributes are:

indexName: the name of the index to store this entity in

type: the mapping type. If not set, the lowercased simple name of the class is used.

shards: the number of shards for the index.

replicas: the number of replicas for the index.

refreshIntervall: Refresh interval for the index. Used for index creation. Default value is "1s".

indexStoreType: Index storage type for the index. Used for index creation. Default value is "fs".

createIndex: Configuration whether to create an index on repository bootstrapping. Default value is true.

versionType: Configuration of version management. Default value is EXTERNAL.

@Transient: By default all private fields are mapped to the document, this annotation excludes the field where it is applied from being stored in the database

@PersistenceConstructor: Marks a given constructor - even a package protected one - to use when instantiating the object from the database. Constructor arguments are mapped by name to the key values in the retrieved Document.

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

name: The name of the field as it will be represented in the Elasticsearch document, if not set, the Java field name is used.

type: the field type, can be one of Text, Integer, Long, Date, Float, Double, Boolean, Object, Auto, Nested, Ip, Attachment, Keyword.

format and pattern custom definitions for the Date type.

store: Flag wether the original field value should be store in Elasticsearch, default value is false.

analyzer, searchAnalyzer, normalizer for specifying custom custom analyzers and normalizer.

copy_to: the target field to copy multiple document fields to.

@GeoPoint: marks a field as geo_point datatype. Can be omitted if the field is an instance of the GeoPoint class.

Mapping Rules

Type Hints

Mapping uses type hints embedded in the document sent to the server to allow generic type mapping. Those type hints are represented as _class attributes within the document and are written for each aggregate root.

public class Person {              

  @Id String id;
  String firstname;
  String lastname;
}
{
  "_class" : "com.example.Person", 
  "id" : "cb7bef",
  "firstname" : "Sarah",
  "lastname" : "Connor"
}


Type Hints with Alias
@TypeAlias("human")                
public class Person {

  @Id String id;
  // ...
}
{
  "_class" : "human",              
  "id" : ...
}


Geospatial Types

Geospatial types like Point & GeoPoint are converted into lat/lon pairs.

public class Address {

  String city, street;
  Point location;
}
{
  "city" : "Los Angeles",
  "street" : "2800 East Observatory Road",
  "location" : { "lat" : 34.118347, "lon" : -118.3026284 }
}


Collections

public class Person {

  // ...

  List<Person> friends;

}
{
  // ...

  "friends" : [ { "firstname" : "Kyle", "lastname" : "Reese" } ]
}

Collections Map


public class Person {

  // ...

  Map<String, Address> knownLocations;

}
{
  // ...

  "knownLocations" : {
    "arrivedAt" : {
       "city" : "Los Angeles",
       "street" : "2800 East Observatory Road",
       "location" : { "lat" : 34.118347, "lon" : -118.3026284 }
     }
  }
}



No comments:

Post a Comment