Skip to content

Latest commit

 

History

History
256 lines (193 loc) · 9.92 KB

elasticsearch-operations.adoc

File metadata and controls

256 lines (193 loc) · 9.92 KB

Elasticsearch Operations

Spring Data Elasticsearch uses several interfaces to define the operations that can be called against an Elasticsearch index (for a description of the reactive interfaces see [elasticsearch.reactive.operations]).

  • IndexOperations defines actions on index level like creating or deleting an index.

  • DocumentOperations defines actions to store, update and retrieve entities based on their id.

  • SearchOperations define the actions to search for multiple entities using queries

  • ElasticsearchOperations combines the DocumentOperations and SearchOperations interfaces.

These interfaces correspond to the structuring of the Elasticsearch API.

The default implementations of the interfaces offer:

  • index management functionality.

  • Read/Write mapping support for domain types.

  • A rich query and criteria api.

  • Resource management and Exception translation.

Note
Index management and automatic creation of indices and mappings.

The IndexOperations interface and the provided implementation which can be obtained from an ElasticsearchOperations instance - for example with a call to operations.indexOps(clazz)- give the user the ability to create indices, put mappings or store template and alias information in the Elasticsearch cluster. Details of the index that will be created can be set by using the @Setting annotation, refer to [elasticsearc.misc.index.settings] for further information.

None of these operations are done automatically by the implementations of IndexOperations or ElasticsearchOperations. It is the user’s responsibility to call the methods.

There is support for automatic creation of indices and writing the mappings when using Spring Data Elasticsearch repositories, see [elasticsearch.repositories.autocreation]

ElasticsearchRestTemplate

The ElasticsearchRestTemplate is an implementation of the ElasticsearchOperations interface using the [elasticsearch.clients.rest].

Example 1. ElasticsearchRestTemplate configuration
@Configuration
public class RestClientConfig extends AbstractElasticsearchConfiguration {
  @Override
  public RestHighLevelClient elasticsearchClient() {       (1)
    return RestClients.create(ClientConfiguration.localhost()).rest();
  }

  // no special bean creation needed                       (2)
}
  1. Setting up the [elasticsearch.clients.rest].

  2. The base class AbstractElasticsearchConfiguration already provides the elasticsearchTemplate bean.

Usage examples

As both ElasticsearchTemplate and ElasticsearchRestTemplate implement the ElasticsearchOperations interface, the code to use them is not different. The example shows how to use an injected ElasticsearchOperations instance in a Spring REST controller. The decision, if this is using the TransportClient or the RestClient is made by providing the corresponding Bean with one of the configurations shown above.

Example 2. ElasticsearchOperations usage
@RestController
@RequestMapping("/")
public class TestController {

  private  ElasticsearchOperations elasticsearchOperations;

  public TestController(ElasticsearchOperations elasticsearchOperations) { (1)
    this.elasticsearchOperations = elasticsearchOperations;
  }

  @PostMapping("/person")
  public String save(@RequestBody Person person) {                         (2)

    IndexQuery indexQuery = new IndexQueryBuilder()
      .withId(person.getId().toString())
      .withObject(person)
      .build();
    String documentId = elasticsearchOperations.index(indexQuery);
    return documentId;
  }

  @GetMapping("/person/{id}")
  public Person findById(@PathVariable("id")  Long id) {                   (3)
    Person person = elasticsearchOperations
      .queryForObject(GetQuery.getById(id.toString()), Person.class);
    return person;
  }
}
  1. Let Spring inject the provided ElasticsearchOperations bean in the constructor.

  2. Store some entity in the Elasticsearch cluster.

  3. Retrieve the entity with a query by id.

To see the full possibilities of ElasticsearchOperations please refer to the API documentation.

Search Result Types

When a document is retrieved with the methods of the DocumentOperations interface, just the found entity will be returned. When searching with the methods of the SearchOperations interface, additional information is available for each entity, for example the score or the sortValues of the found entity.

In order to return this information, each entity is wrapped in a SearchHit object that contains this entity-specific additional information. These SearchHit objects themselves are returned within a SearchHits object which additionally contains informations about the whole search like the maxScore or requested aggregations. The following classes and interfaces are now available:

SearchHit<T>

Contains the following information:

  • Id

  • Score

  • Sort Values

  • Highlight fields

  • Inner hits (this is an embedded SearchHits object containing eventually returned inner hits)

  • The retrieved entity of type <T>

SearchHits<T>

Contains the following information:

  • Number of total hits

  • Total hits relation

  • Maximum score

  • A list of SearchHit<T> objects

  • Returned aggregations

  • Returned suggest results

SearchPage<T>

Defines a Spring Data Page that contains a SearchHits<T> element and can be used for paging access using repository methods.

SearchScrollHits<T>

Returned by the low level scroll API functions in ElasticsearchRestTemplate, it enriches a SearchHits<T> with the Elasticsearch scroll id.

SearchHitsIterator<T>

An Iterator returned by the streaming functions of the SearchOperations interface.

Queries

Almost all of the methods defined in the SearchOperations and ReactiveSearchOperations interface take a Query parameter that defines the query to execute for searching. Query is an interface and Spring Data Elasticsearch provides three implementations: CriteriaQuery, StringQuery and NativeSearchQuery.

CriteriaQuery

CriteriaQuery based queries allow the creation of queries to search for data without knowing the syntax or basics of Elasticsearch queries. They allow the user to build queries by simply chaining and combining Criteria objects that specifiy the criteria the searched documents must fulfill.

Note
when talking about AND or OR when combining criteria keep in mind, that in Elasticsearch AND are converted to a must condition and OR to a should

Criteria and their usage are best explained by example (let’s assume we have a Book entity with a price property):

Example 3. Get books with a given price
Criteria criteria = new Criteria("price").is(42.0);
Query query = new CriteriaQuery(criteria);

Conditions for the same field can be chained, they will be combined with a logical AND:

Example 4. Get books with a given price
Criteria criteria = new Criteria("price").greaterThan(42.0).lessThan(34.0L);
Query query = new CriteriaQuery(criteria);

When chaining Criteria, by default a AND logic is used:

Example 5. Get all persons with first name James and last name Miller:
Criteria criteria = new Criteria("lastname").is("Miller") (1)
  .and("firstname").is("James")                           (2)
Query query = new CriteriaQuery(criteria);
  1. the first Criteria

  2. the and() creates a new Criteria and chaines it to the first one.

If you want to create nested queries, you need to use subqueries for this. Let’s assume we want to find all persons with a last name of Miller and a first name of either Jack or John:

Example 6. Nested subqueries
Criteria miller = new Criteria("lastName").is("Miller")  (1)
  .subCriteria(                                          (2)
    new Criteria().or("firstName").is("John")            (3)
      .or("firstName").is("Jack")                        (4)
  );
Query query = new CriteriaQuery(criteria);
  1. create a first Criteria for the last name

  2. this is combined with AND to a subCriteria

  3. This sub Criteria is an OR combination for the first name John

  4. and the first name Jack

Please refer to the API documentation of the Criteria class for a complete overview of the different available operations.

StringQuery

This class takes an Elasticsearch query as JSON String. The following code shows a query that searches for persons having the first name "Jack":

Query query = new SearchQuery("{ \"match\": { \"firstname\": { \"query\": \"Jack\" } } } ");
SearchHits<Person> searchHits = operations.search(query, Person.class);

Using StringQuery may be appropriate if you already have an Elasticsearch query to use.

NativeSearchQuery

NativeSearchQuery is the class to use when you have a complex query, or a query that cannot be expressed by using the Criteria API, for example when building queries and using aggregates. It allows to use all the different QueryBuilder implementations from the Elasticsearch library therefore named "native".

The following code shows how to search for persons with a given firstname and for the found documents have a terms aggregation that counts the number of occurences of the lastnames for these persons:

Query query = new NativeSearchQueryBuilder()
    .addAggregation(terms("lastnames").field("lastname").size(10)) //
    .withQuery(QueryBuilders.matchQuery("firstname", firstName))
    .build();

SearchHits<Person> searchHits = operations.search(query, Person.class);