What's new in Spring Data Elasticsearch 4.0

Engineering | Mark Paluch | May 27, 2020 | ...

This article continues our blog post series on What’s new in Spring Data Neumann. Today’s installment explains New and Noteworthy in Spring Data Elasticsearch. This blog post was written by P.J. Meisch who maintains the Spring Data Elasticsearch module.

This release addresses more than 140 issues, with more than 30 bugs fixed.

Spring Data Elasticsearch now uses Elasticsearch 7, 7.6.2 in particular. Elasticsearch clusters running on 6.x versions are not supported anymore. The ElasticsearchTemplate class is deprecated as it uses the TransportClient to access Elasticsearch, which itself is deprecated since Elasticsearch version 7.+ Users should switch to ElasticsearchRestTemplate or ReactiveElasticsearchTemplate.

In general, this release ships with several changes that may require several updates to your code and domain model. You can find the entire migration guide in the reference documentation.

Improved object mapping and entity definitions

A change under the hood was that the mapping between an entity to the JSON document that elasticsearch needs was switched from using Jackson to the MappingElasticsearchConverter. Now it is possible to define custom names for properties and even different date formats for time-related properties without the problems that used to show up in the previous versions. The MappingElasticsearchConverter not only converts entities but is also used when building queries and processing search results. By this the mapping and conversion is consistently applied to the whole storage and search process.

The @Field annotation now supports nearly all of the types that can be used in Elasticsearch.

@Document(indexName = "person", type = "dummy")
public class Person implements Persistable<Long> {

    @Nullable @Id
    private Long id;

    @Nullable @Field(value = "last-name", type = FieldType.Text, fielddata = true)
    private String lastName;      (1)

    @Nullable @Field(name = "birth-date", type = FieldType.Date, format = DateFormat.basic_date)
    private LocalDate birthDate;  (2)

    @Nullable @Field(type = FieldType.Date, format = DateFormat.basic_date_time)
    private Instant created;      (3)

    // other properties, getter, setter
  1. in Elasticsearch this field will be named last-name, this mapping is handled transparently

  2. a property for a date without time information

  3. another property this time with full date and time information

New return types

As Elasticsearch not only returns the found entities in search results but a lot of additional information as well, new classes are introduced to provide this information, the most important being:

  • SearchHit<T> contains the entity and information like the score, sortvalues, highlight fields

  • SearchHits<T> contains the maxScore of a search, returned aggregations, the totalCount, and the list of SearchHit<T> elements.

These are returned from the calls to the (Reactive)ElasticsearchOperations.

To use them with repository methods they just need to be defined as the return type (repositories also support paged requests). As it is now possible to access highlight values in the SearchHit, repository methods can now be configured for highlights like shown in the first method:

@Highlight(fields = {@HighlightField(name = "firstName")})
List<SearchHit<Person>> findByFirstName(String firstName);

Stream<SearchHit<Person>> findByBirthDateAfter(LocalDate date);

SearchHits<Person> findByLastName(String lastName);

SearchPage<Person> searchByLastName(String name, Pageable pageable);

Of course it is still possible to retrieve just the entity by defining the return type as List<Person>.

Additional configuration options

Both the reactive and the non-reactive client can be configured with additional parameters

  • SSL support optionally with a custom SSLContext

  • Proxy support

  • custom header supplier to dynamically provide headers for each request sent to the cluster

  • pathPrefix for cases where the Elasticsearch cluster is behind some Loadbalancer or dispatcher

Entity callbacks and Auditing

It now is possible to define Entity callbacks, the followig table shows the supported callbacks:





onBeforeConvert(T, IndexCoordinates)

Invoked before a domain object is converted to Document.
Can return the entity or a modified entity which then will be converted.


onAfterConvert(T, Document, IndexCoordinates)

Invoked after a domain object is converted from Document
on reading result data from Elasticsearch.


onBeforeConvert(Object, IndexCoordinates)

Marks an auditable entity created or modified


T onAfterSave(T, IndexCoordinates)

Invoked after a domain object is saved.

Built upon the AuditingEntityCallback is the support for auditing. By implementing Persistable<T> and adding annotated properties, these values will be automatically maintained for entities stored in Elasticsearch:

@Document(indexName = "person")
public class Person implements Persistable<Long> {

    @Nullable @Id
    private Long id;

    @Nullable @Field(type = FieldType.Date, format = DateFormat.basic_date_time)
    private Instant created;

    @Nullable @CreatedBy
    private String createdBy;

    @Nullable @Field(type = FieldType.Date, format = DateFormat.basic_date_time)
    private Instant lastModified;

    @Nullable @LastModifiedBy
    private String lastModifiedBy;

    public Long getId() { return id; }

    public boolean isNew() { return id == null || (createdBy == null && created == null); }

    // other properties, getter, setter...

Get the Spring newsletter

Thank you!

Get ahead

VMware offers training and certification to turbo-charge your progress.

Learn more

Get support

Spring Runtime offers support and binaries for OpenJDK™, Spring, and Apache Tomcat® in one simple subscription.

Learn more

Upcoming events

Check out all the upcoming events in the Spring community.

View all