Approximate kNN search

Approximate kNN search uses graph-based or clustered index structures to find similar vectors quickly at scale. Use it for most production workloads where you need low latency at scale. This page covers approximate kNN search methods, a basic example, mapping defaults, indexing considerations, and vector index mode.

Tip

If you use semantic_text fields, query them with a match query for the simplest approach, or use the knn query when you need more control over the search.

Warning

Approximate kNN search has specific resource requirements. For instance, for HNSW, all vector data must fit in the node’s page cache for efficient performance. Refer to the approximate kNN tuning guide for configuration tips.

Elasticsearch provides three ways to run approximate kNN search, with different field type support:

Method Supported field types Use case
Top-level knn option dense_vector Standalone kNN search or hybrid search with score fusion
knn query dense_vector, semantic_text Composable with other queries in a bool clause. Required for semantic_text fields
knn retriever dense_vector Use within a retriever pipeline for ranking and result merging

Follow these steps to map dense_vector fields, index embeddings, and run a basic approximate kNN query.

  1. Map one or more dense_vector fields. Approximate kNN search is enabled by default, so no extra mapping options are required.

    Optionally, you can configure additional parameters, including the similarity metric, index options, and quantization. Refer to dense_vector for the full list of parameters.

    				PUT image-index
    					{
      "mappings": {
        "properties": {
          "image-vector": {
            "type": "dense_vector",
            "similarity": "l2_norm"
          },
          "title": {
            "type": "text"
          },
          "file-type": {
            "type": "keyword"
          }
        }
      }
    }
    		
  2. Index your data with embeddings. If you don't have vectors yet, refer to Bring your own dense vectors for options on generating or sourcing them.

    				POST image-index/_bulk?refresh=true
    					{ "index": { "_id": "1" } }
    { "image-vector": [1, 5, -20], "title": "moose family", "file-type": "jpg" }
    { "index": { "_id": "2" } }
    { "image-vector": [42, 8, -15], "title": "alpine lake", "file-type": "png" }
    { "index": { "_id": "3" } }
    { "image-vector": [15, 11, 23], "title": "full moon", "file-type": "jpg" }
    ...
    		
  3. Query using the knn option:

    				POST image-index/_search
    					{
      "knn": {
        "field": "image-vector",
        "query_vector": [-5, 9, -12],
        "k": 10
      }
    }
    		

    Alternatively, use a knn query, which you can combine with other queries in a bool clause:

    				POST image-index/_search
    					{
      "query": {
        "knn": {
          "field": "image-vector",
          "query_vector": [-5, 9, -12],
          "k": 10
        }
      }
    }
    		

The document _score is a positive float calculated based on the chosen vector similarity metric. Refer to similarity for details on how kNN scores are computed.

Approximate kNN works without any explicit mapping options. Unless you set them, Elasticsearch applies these defaults:

Parameter Default
index true, so the field is searchable with approximate kNN
element_type float
dims Inferred from the first vector indexed into the field
similarity cosine, except for bit vectors, which use l2_norm
index_options.type float and bfloat16 vectors are quantized automatically, using BBQ where available and int8_hnsw for low-dimensional vectors. byte and bit vectors are not quantized.

The index_options.type default is particularly important: by default your float vectors are quantized, which is what keeps memory use manageable at scale. Refer to Default quantization types for how the default is chosen, and to Optimize performance and accuracy if you need to override it.

For approximate kNN, Elasticsearch indexes dense vector values as an HNSW graph or as clusters using DiskBBQ. Building these structures is compute-intensive. GPU-accelerated vector indexing is also supported. To reduce memory use and speed up vector distance calculations, Elasticsearch also quantizes vectors.

Quantization comes at the expense of recall, which you can compensate for by oversampling and rescoring more vectors. The hnsw and bbq_disk types each come with their own settings to balance recall, indexing speed, and vector search speed.

For guidance on choosing and tuning these settings, refer to the approximate kNN tuning guide. When defining your dense_vector mapping, use index_options to set these parameters.

If an index is used primarily for vector search, create it with the vectordb_document index mode to get defaults tuned for vector workloads:

				PUT my-vector-index
					{
  "settings": {
    "index": {
      "mode": "vectordb_document"
    }
  }
}
		

In this mode, Elasticsearch encodes vectors as bfloat16 to halve raw vector storage, excludes vector values from _source, preloads vector index files into the filesystem cache, and tunes merging for vector data.

Refer to Index modes for vector search for the full list of applied settings.

  • Tune approximate kNN search: Production guidance for vector memory, node sizing, indexing, filesystem cache, and on-disk rescoring.
  • Profile kNN search: Inspect query timing and vector operation counts to diagnose slow kNN searches.
  • dense_vector field type: API reference for vector field mapping, including index, similarity, index_options, and quantization parameters.
  • knn query: API reference for the knn query, including parameters, query_vector_builder options, and usage with dense_vector and semantic_text fields.