This version is still in development and is not considered stable yet. For the latest stable version, please use Spring Data Elasticsearch 5.4.0! |
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).
-
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 theDocumentOperations
andSearchOperations
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.
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.
The following classes and interfaces are now available:
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>
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.