Try out vector search for yourself using this self-paced hands-on learning for Search AI. You can start a free cloud trial or try Elastic on your local machine now.
The use of embeddings to improve the relevance and accuracy of information retrieval has grown significantly over the years. Tools like Elasticsearch have evolved to support this type of data through specialized field types such as dense vectors, sparse vectors, and semantic text. However, to achieve good results, it is essential to understand how to properly map embeddings to the available Elasticsearch field types: semantic_text, dense_vector, and sparse_vector.
In this article, we will discuss these field types, when to use each one, and how they relate to embedding generation and usage strategies, both during indexing and querying.
Dense vector type
The dense_vector field type in Elasticsearch is used to store dense vectors, which are numerical representations of text where almost all dimensions are relevant. These vectors are generated by language models, such as OpenAI, Cohere, and Hugging Face, and are designed to capture the overall semantic meaning of a text, even when it does not share exact terms with other documents.
In Elasticsearch, dense vectors can have up to 4096 dimensions depending on the model used. For example, the all-MiniLM-L6-v2 model generates vectors with 384 dimensions, while OpenAI’s text-embedding-ada-002 produces vectors with 1536 dimensions.
The dense_vector field is commonly adopted as the default type for storing this kind of embedding when greater control is needed, such as using pre-generated vectors, applying custom similarity functions, or integrating with external models.
When and why to use dense_vector type?
Dense vectors are excellent for capturing semantic similarity between sentences, paragraphs, or entire documents. They work very well when the goal is to compare the overall meaning of texts, even if they do not share the same terms.
The dense vector field is ideal when you already have an external embedding generation pipeline using models such as OpenAI, Cohere, or Hugging Face and only want to store and query these vectors manually. This type of field offers high compatibility with embedding models and full flexibility in generation and querying, allowing you to control how the vectors are produced, indexed, and used during search.
In addition, it supports different forms of semantic search, with queries such as KNN or script_score for cases where it is necessary to adjust the ranking logic. These possibilities make the dense vector ideal for applications such as RAG (Retrieval-Augmented Generation), recommendation systems, and personalized searches based on similarity.
Finally, the field allows you to customize the relevance logic, using functions such as cosineSimilarity, dotProduct or l2norm to adapt the ranking according to the needs of your use case.
Dense vectors remain the best option for those who need flexibility, customization, and compatibility with advanced use cases like the ones mentioned above.
How to use the query for dense vector type?
Searches on fields defined as dense_vector use the k-nearest neighbor query. This query is responsible for finding documents whose dense vector is closest to the query vector. Below is an example of how to apply a Knn query to a dense vector field:
In addition to the Knn query, if there is a need to customize the document scoring, it is also possible to use the script_score query, combining it with vector comparison functions such as cosineSimilarity, dotProduct, or l2norm to calculate relevance in a more controlled way. See the example:
If you want to dive deeper, I recommend exploring the article How to set up vector search in Elasticsearch.
Sparse vector type
The sparse_vector field type is used to store sparse vectors, which are numerical representations where most values are zero and only a few terms have significant weights. This type of vector is common in term-based models such as SPLADE or ELSER (Elastic Learned Sparse EncodeR).
When and why to use sparse vector type?
Sparse vectors are ideal when you need a more precise search in lexical terms, without sacrificing semantic intelligence. They represent the text as token/value pairs, highlighting only the most relevant terms with associated weights, which provides clarity, control and efficiency.
This type of field is especially useful when you generate vectors based on terms, such as in the ELSER or SPLADE models, which assign different weights to each token based on its relative importance in the text.
For the occasions when you want to control the influence of specific words in the query, sparse vector types allow you to manually adjust the weight of the terms to optimize the ranking of the results.
Among the main benefits are transparency in the search since it is possible to clearly understand why a document was considered relevant, and storage efficiency since only tokens with a non-zero value are saved, unlike dense vectors that store all dimensions.
Furthermore, sparse vectors are the ideal complement in hybrid search strategies, and can even be combined with dense vectors to combine lexical precision with semantic understanding.
How to use the query for sparse vector type?
The sparse_vector query allows you to search for documents based on a query vector in token/value format. See an example of the query below:
If you prefer to use a trained model, it is possible to use an inference endpoint that automatically transforms the query text into a sparse vector:
To explore this topic further, I suggest reading Understanding sparse vector embeddings with trained ML models.
Semantic text type
The semantic_text field type is the simplest and most straightforward way to use semantic search in Elasticsearch. It automatically handles embedding generation, both at indexing and query time, through an inference endpoint. This means you don’t have to worry about generating or storing vectors manually.
When and why to use semantic text?
The semantic_text field is the simplest and most straightforward way to adopt semantic search in Elasticsearch. It is ideal for those who want to get started with minimal technical effort and without having to handle vectors manually. This field automates steps like embedding generation and vector search mapping, making the setup faster and more convenient.
You should consider using semantic_text when you value simplicity and abstraction, as it eliminates the complexity of manually configuring mappings, embedding generation, and ingestion pipelines. Just select the inference model, and Elasticsearch takes care of the rest.
Key advantages include automatic embedding generation, performed during both indexing and querying, and ready-to-use mapping, which comes preconfigured to support the selected inference model.
In addition, the field offers native support for automatic splitting of long texts (text chunking), allowing large texts to be divided into smaller passages, each with its own embedding, which improves search precision. This greatly boosts productivity, especially for teams that want to deliver value quickly without dealing with the underlying engineering of semantic search.
However, while semantic_text provides speed and simplicity, this approach has some limitations. It allows the use of market standard models, as long as they are available as inference endpoints in Elasticsearch. But it does not support externally generated embeddings, as is possible with the dense_vector field.
If you need more control over how vectors are generated, want to use your own embeddings, or need to combine multiple fields for advanced strategies, the dense_vector and sparse_vector fields provide the flexibility required for more customized or domain-specific scenarios.
How to use the query for semantic text type
Before semantic_text, it was necessary to use a different query depending on the type of embedding (dense or sparse). A sparse_vector query was used for sparse fields, while dense_vector fields required KNN queries.
With the semantic text type, the search is performed using the semantic query, which automatically generates the query vector and compares it with the embeddings of the indexed documents. The semantic_text type allows you to define an inference endpoint to embed the query, but if none is specified, the same endpoint used during indexing will be applied to the query.
To learn more, I suggest reading the article Elasticsearch new semantic_text mapping: Simplifying semantic search.
Conclusion
When choosing how to map embeddings in Elasticsearch, it is essential to understand how you want to generate the vectors and what level of control you need over them. If you are looking for simplicity, the semantic text field enables automatic and scalable semantic search, making it ideal for many initial use cases. When more control, fine-tuned performance, or integration with custom models is required, the dense vector and sparse vector fields provide the necessary flexibility.
The ideal field type depends on your use case, available infrastructure, and the maturity of your machine learning stack. Most importantly, Elastic offers the tools to build modern and highly adaptable search systems.
References
- Semantic text field type
- Sparse vector field type
- Dense vector field type
- Semantic query
- Sparse vector query
- kNN search
- Elasticsearch new semantic_text mapping: Simplifying semantic search
- Understanding sparse vector embeddings with trained ML models