In 8.14, Elastic introduced a new search capability called “Retrievers” in Elasticsearch. Keep reading to discover their simplicity and efficiency and how they can empower you in your search operations.
Retrievers are a new abstraction layer added to the Search API in Elasticsearch. They offer the convenience of configuring multi-stage retrieval pipelines within a single _search
API call. This architecture simplifies search logic in your application by eliminating the need for multiple Elasticsearch API calls for complex search queries. It also reduces the need for client-side logic, often required to combine results from multiple queries.
Initial types of Retrievers
There are three types of retrievers included in the initial release. Each of these retrievers is designed for a specific purpose, and when combined, they allow for complex search operations.
The available types are:
- Standard - Return the top documents from a traditional query. These allow backward compatibility by supporting existing Query DSL request syntax, allowing you to migrate to the retriever framework at your own pace.
- kNN - Return the top documents from a kNN search.
- RRF - Combine and rank multiple first-stage retrievers into a single result set with no or minimal user tuning using the reciprocal rank fusion algorithm. An RRF retriever is a compound retriever whose filter element is propagated to its sub-retrievers.
How are Retrievers different, and why are they useful?
With traditional queries, the query is part of the overall search API call. Retrievers differ by being designed as standalone entities that can be used in isolation or easily combined. This modular approach allows for more flexibility when designing search strategies.
Retrievers are designed to be part of a “retriever tree,” a hierarchical structure that defines search operations by clarifying their sequence and logic. This structure makes complex searches more manageable and easier for developers to understand and allows new functionality to be easily added in the future.
Retrievers enable composability, allowing you to build pipelines and integrate different retrieval strategies. This allows for easy testing of varying retrieval combinations. They also provide more control over how documents are scored and filtered. You can, for example, specify a minimum score threshold, apply a complex filter without affecting scoring, and use parameters like terminate_after
for performance optimizations.
Backward compatibility is maintained with traditional query elements, automatically translating them to the appropriate retriever.
Retrievers usage examples
Let’s look at some examples of using retrievers. We are using an IMDB sample dataset.
You can run the accompying jupyter notebook to ingest IMDB data into a Serverless Search project and run the below examples yourself!
The high-level setup is:
overview
- a short summary of the movienames
the movie's nameoverview_dense
- a dense_vector generated from ane5-small
modeloverview_sparse
- a sparse vector using Elastic’sELSER
model.- Only returning the text version of
names
andoverview
usingfields
and setting_source:false
Standard - Search All the Text!
GET /imdb_movies/_search?pretty
{
"retriever": {
"standard": {
"query": {
"term": {
"overview": "clueless"
}
}
}
},
"size": 3,
"fields": [
"names",
"overview"
],
"_source": false
}
kNN - Search all the Dense Vectors!
GET /imdb_movies/_search?pretty
{
"retriever": {
"knn": {
"field": "overview_dense",
"query_vector_builder": {
"text_embedding": {
"model_id": ".multilingual-e5-small_linux-x86_64",
"model_text": "clueless slackers"
}
},
"k": 5,
"num_candidates": 5
}
},
"size": 3,
"fields": [
"names",
"overview"
],
"_source": false
}
text_expansion - Search all the Sparse Vectors!
GET /imdb_movies/_search?pretty
{
"retriever": {
"standard": {
"query": {
"text_expansion": {
"overview_sparse": {
"model_id": ".elser_model_2_linux-x86_64",
"model_text": "clueless slackers"
}
}
}
}
},
"size": 3,
"fields": [
"names",
"overview"
],
"_source": false
}
rrf - Combine All the Things!
GET /imdb_movies/_search?pretty
{
"retriever": {
"rrf": {
"retrievers": [
{
"standard": {
"query": {
"term": {
"overview": "clueless slackers"
}
}
}
},
{
"knn": {
"field": "overview_dense",
"query_vector_builder": {
"text_embedding": {
"model_id": ".multilingual-e5-small_linux-x86_64",
"model_text": "clueless slackers"
}
},
"k": 5,
"num_candidates": 5
}
},
{
"standard": {
"query": {
"text_expansion": {
"overview_sparse": {
"model_id": ".elser_model_2_linux-x86_64",
"model_text": "clueless slackers"
}
}
}
}
}
],
"rank_window_size": 5,
"rank_constant": 1
}
},
"size": 3,
"fields": [
"names",
"overview"
],
"_source": false
}
Current restrictions with Retrievers
Retrievers come with certain restrictions users should be aware of. For example, only the query element is allowed when using compound retrievers. This enforces a cleaner separation of concerns and prevents the complexity from overly nested or independent configurations. Additionally, sub-retrievers may not use elements restricted from having a compound retriever as part of the retriever tree.
These restrictions enforce performance and composability even with complex retrieval strategies.
Retrievers are initially released as a technical preview, so their API may change.
Conclusion
Retrievers represent a significant step forward with Elasticsearch's retrieval capabilities and user-friendliness. They can be chained in a pipeline fashion where each retriever applies its logic and passes the results to the next item in the chain. By allowing for more structured, flexible, and efficient search operations, retrievers can significantly enhance the search experience.
The following resources provide additional details on Retrievers.
- Semantic Reranking in Elasticsearch with Retrievers
- Retrievers API documentation
- Retrievers - Search Your Data documentation
Try the above code yourself! You can run the accompying jupyter notebook to ingest IMDB data into an Elastic Serverless Search project!