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 Reactive Elasticsearch Operations).
-
IndexOperationsdefines actions on index level like creating or deleting an index. -
DocumentOperationsdefines actions to store, update and retrieve entities based on their id. -
SearchOperationsdefine the actions to search for multiple entities using queries -
ElasticsearchOperationscombines theDocumentOperationsandSearchOperationsinterfaces.
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.
|
Index management and automatic creation of indices and mappings.
The None of these operations are done automatically by the implementations of There is support for automatic creation of indices and writing the mappings when using Spring Data Elasticsearch repositories, see Automatic creation of indices with the corresponding mapping |
Usage examples
The example shows how to use an injected ElasticsearchOperations instance in a Spring REST controller.
The example assumes that Person is a class that is annotated with @Document, @Id etc (see Mapping Annotation Overview).
@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)
Person savedEntity = elasticsearchOperations.save(person);
return savedEntity.getId();
}
@GetMapping("/person/{id}")
public Person findById(@PathVariable("id") Long id) { (3)
Person person = elasticsearchOperations.get(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.
The id is read from the returned entity, as it might have been null in the person object and been created by Elasticsearch. |
| 3 | Retrieve the entity with a get 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 or the execution duration it took to complete the request.
The following classes and interfaces are now available:
Contains the following information:
-
Id
-
Score
-
Sort Values
-
Highlight fields
-
Inner hits (this is an embedded
SearchHitsobject containing eventually returned inner hits) -
The retrieved entity of type <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
Defines a Spring Data Page that contains a SearchHits<T> element and can be used for paging access using repository methods.
Returned by the low level scroll API functions in ElasticsearchRestTemplate, it enriches a SearchHits<T> with the Elasticsearch scroll id.
An Iterator returned by the streaming functions of the SearchOperations interface.
ReactiveSearchOperations has methods returning a Mono<ReactiveSearchHits<T>>, this contains the same information as a SearchHits<T> object, but will provide the contained SearchHit<T> objects as a Flux<SearchHit<T>> and not as a list.
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 NativeQuery.
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 specify the criteria the searched documents must fulfill.
| 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):
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:
Criteria criteria = new Criteria("price").greaterThan(42.0).lessThan(34.0);
Query query = new CriteriaQuery(criteria);
When chaining Criteria, by default a AND logic is used:
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:
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 StringQuery("{ \"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.
NativeQuery
NativeQuery 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 co.elastic.clients.elasticsearch._types.query_dsl.Query 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 occurrences of the lastName for these persons:
Query query = NativeQuery.builder()
.withAggregation("lastNames", Aggregation.of(a -> a
.terms(ta -> ta.field("lastName").size(10))))
.withQuery(q -> q
.match(m -> m
.field("firstName")
.query(firstName)
)
)
.withPageable(pageable)
.build();
SearchHits<Person> searchHits = operations.search(query, Person.class);
SearchTemplateQuery
This is a special implementation of the Query interface to be used in combination with a stored search template.
See Search Template support for further information.