docs/reference/elasticsearch/mapping-reference/semantic-text-search-retrieval.md
semantic_text fields [set-up-configuration-semantic-text]This page provides instructions for searching and retrieving data from semantic_text fields. Learn how to query semantic_text fields, retrieve indexed chunks, retrieve field embeddings, and highlight the most relevant fragments from search results.
semantic_text fields [querying-semantic-text-fields]You can query semantic_text fields using the following query types:
Match query: The recommended method for querying semantic_text fields. You can use Query DSL or ES|QL syntax. To learn how to run match queries on semantic_text fields, refer to this example.
kNN query: Finds the nearest vectors to a query vector using a similarity metric, mainly for advanced or combined search use cases. You can use Query DSL or {applies_to}stack: ga 9.2 ES|QL syntax. To learn how to run knn queries on semantic_text fields, refer to this example.
Sparse vector query: Executes searches using sparse vectors generated by a sparse retrieval model such as ELSER. You can use it with Query DSL syntax. To learn how to run sparse vector queries on semantic_text fields, refer to this example.
Semantic query: We don't recommend this legacy query type for new projects, because the alternatives in this list enable more flexibility and customization. The semantic query remains available to support existing implementations.
stack: ga 9.2
serverless: ga
You can retrieve the individual chunks generated by your semantic field's chunking strategy using the fields parameter:
POST test-index/_search
{
"query": {
"ids" : {
"values" : ["1"]
}
},
"fields": [
{
"field": "semantic_text_field",
"format": "chunks" <1>
}
]
}
% TEST[skip:Requires {{infer}} endpoint]
"format": "chunks" to return the field's text as the original text chunks that were indexed.semantic_text field embeddings [returning-semantic-field-embeddings]By default, embeddings generated for semantic_text fields are stored internally and not included in the response when retrieving documents. Retrieving embeddings is useful when you want to:
inference_id without re-running {{infer}}The method for retrieving embeddings depends on your {{es}} version:
_source.exclude_vectors parameter to include embeddings in _source.fields parameter with _inference_fields to retrieve embeddings._source [returning-semantic-field-embeddings-in-_source]stack: ga 9.2
serverless: ga
To include the full {{infer}} fields, including their embeddings, in _source, set the _source.exclude_vectors option to false:
POST my-index/_search
{
"_source": {
"exclude_vectors": false
},
"query": {
"match_all": {}
}
}
% TEST[skip:Requires {{infer}} endpoint]
The embeddings will appear under _inference_fields in _source.
This works with the Get, Search, and Reindex APIs.
stack: ga 9.2
serverless: ga
When reindexing documents with semantic_text fields, you can preserve existing embeddings by including them in the source documents. This allows documents to be re-indexed without triggering {{infer}} again.
::::{warning}
The target index's semantic_text field must use the same inference_id as the source index to reuse existing embeddings. If the inference_id values do not match, the documents will fail the reindex task.
::::
POST _reindex
{
"source": {
"index": "my-index-src",
"_source": {
"exclude_vectors": false <1>
}
},
"dest": {
"index": "my-index-dest"
}
}
% TEST[skip:Requires {{infer}} endpoint]
semantic_text fields [troubleshooting-semantic-text-fields]stack: ga 9.2
serverless: ga
To verify that your embeddings look correct or debug embedding generation, retrieve the stored embeddings:
POST test-index/_search
{
"_source": {
"exclude_vectors": false
},
"query": {
"match": {
"my_semantic_field": "Which country is Paris in?"
}
}
}
% TEST[skip:Requires {{infer}} endpoint]
This will return verbose chunked embeddings content that is used to perform
semantic search for semantic_text fields:
{
"took": 18,
"timed_out": false,
"_shards": {
"total": 1,
"successful": 1,
"skipped": 0,
"failed": 0
},
"hits": {
"total": { "value": 1, "relation": "eq" },
"max_score": 16.532316,
"hits": [
{
"_index": "test-index",
"_id": "1",
"_score": 16.532316,
"_source": {
"my_semantic_field": "Paris is the capital of France.",
"_inference_fields": {
"my_semantic_field": {
"inference": {
"inference_id": ".elser-2-elasticsearch", <1>
"model_settings": { <2>
"service": "elasticsearch",
"task_type": "sparse_embedding"
},
"chunks": {
"my_semantic_field": [
{
"start_offset": 0,
"end_offset": 31,
"embeddings": { <3>
"airport": 0.12011719,
"brussels": 0.032836914,
"capital": 2.1328125,
"capitals": 0.6386719,
"capitol": 1.2890625,
"cities": 0.78125,
"city": 1.265625,
"continent": 0.26953125,
"country": 0.59765625,
...
}
}
]
}
}
}
}
}
}
]
}
}
% TEST[skip:Requires {{infer}} endpoint]
fields [returning-semantic-field-embeddings-using-fields]:::{important}
This method for returning semantic field embeddings is recommended only for {{es}} versions earlier than 9.2.
For version 9.2 and later, use the exclude_vectors parameter instead.
:::
To retrieve stored embeddings, use the fields parameter with _inference_fields. This lets you include the vector data that is not shown by default in the response.
POST my-index/_search
{
"query": {
"match": {
"my_semantic_field": "Which country is Paris in?"
}
},
"fields": [
"_inference_fields"
]
}
% TEST[skip:Requires {{infer}} endpoint]
The fields parameter works with the Search API.
Extract the most relevant fragments from a semantic_text field using the highlight parameter in the Search API.
:::::{stepper}
::::{step} Highlight semantic_text fields
Use the highlight parameter with number_of_fragments and order to control fragment selection and sorting:
POST test-index/_search
{
"query": {
"match": {
"my_semantic_field": "Which country is Paris in?"
}
},
"highlight": {
"fields": {
"my_semantic_field": {
"number_of_fragments": 2, <1>
"order": "score" <2>
}
}
}
}
% TEST[skip:Requires {{infer}} endpoint]
score. By default, fragments are output in the order they appear in the field (order: none).::::
::::{step} Enforce semantic highlighter
To restrict highlighting to the semantic highlighter and return no fragments when the field is not of type semantic_text, explicitly set the highlighter type to semantic:
POST test-index/_search
{
"query": {
"match": {
"my_field": "Which country is Paris in?"
}
},
"highlight": {
"fields": {
"my_field": {
"type": "semantic", <1>
"number_of_fragments": 2,
"order": "score"
}
}
}
}
% TEST[skip:Requires {{infer}} endpoint]
semantic_text fields.::::
::::{step} Retrieve fragments in original order
To retrieve all fragments from the semantic highlighter in their original indexing order without scoring, use a match_all query as the highlight_query:
POST test-index/_search
{
"query": {
"ids": {
"values": ["1"]
}
},
"highlight": {
"fields": {
"my_semantic_field": {
"number_of_fragments": 5, <1>
"highlight_query": { "match_all": {} }
}
}
}
}
% TEST[skip:Requires {{infer}} endpoint]
::::
:::::
semantic_text fields [result-diversification]stack: preview 9.4
serverless: preview
The diversify retriever supports the use of semantic_text field types for result diversification.
:::{note}
The semantic_text field must use dense_vector embeddings such as those from text_embedding inference tasks.
You must also provide either a query_vector or a query_vector_builder.
:::
POST test-index/_search
{
"retriever": {
"diversify": {
"type": "mmr",
"field": "my_semantic_field",
"lambda": 0.9,
"size": 3,
"query_vector": [0.1, 3.2, 2.1],
"retriever": {
"standard": {
"query": {
"match": {
"my_semantic_field": {
"query": "What causes muscle soreness after running?"
}
}
}
}
}
}
}
}
semantic_text [cross-cluster-search]stack: ga 9.2
serverless: unavailable
::::{applies-switch}
:::{applies-item} stack: ga 9.3+
semantic_text supports {{ccs}} (CCS) through:
_search endpoint when ccs_minimize_roundtrips is true or false.Query semantic_text fields across clusters using the standard _search endpoint with cluster notation:
POST local-index,remote-cluster:remote-index/_search <1>
{
"query": {
"match": {
"my_semantic_field": "Which country is Paris in?"
}
}
}
remote-cluster:remote-index refers to an index on the remote cluster with alias remote-cluster.The same notation can be used to query semantic_text fields across clusters with ES|QL:
POST _query
{
"query": """FROM local-index,remote-cluster:remote-index METADATA _score | <1>
WHERE MATCH(my_semantic_field, "Which country is Paris in?") |
SORT _score DESC |
KEEP my_semantic_field | LIMIT 10
"""
}
remote-cluster:remote-index refers to an index on the remote cluster with alias remote-cluster.
::::::{applies-item} stack: ga =9.2
semantic_text supports {{ccs}} (CCS) through the _search endpoint when ccs_minimize_roundtrips is set to true.
This is the default value, so most CCS queries work automatically.
CCS is not supported in retrievers or ES|QL.
Query semantic_text fields across clusters using the standard _search endpoint with cluster notation:
POST local-index,remote-cluster:remote-index/_search <1>
{
"query": {
"match": {
"my_semantic_field": "Which country is Paris in?"
}
}
}
remote-cluster:remote-index refers to an index on the remote cluster with alias remote-cluster.
:::::::