﻿---
title: Dense vectors and kNN search
description: When working with vector embeddings for semantic search or machine learning applications, the Go client provides support for dense vector indexing and...
url: https://www.elastic.co/elastic/docs-builder/docs/3174/reference/elasticsearch/clients/go/using-the-api/dense-vectors
products:
  - Elasticsearch
  - Elasticsearch Client
  - Elasticsearch Go Client
---

# Dense vectors and kNN search
<applies-to>
  - Elastic Stack: Generally available since 9.3
</applies-to>

When working with vector embeddings for semantic search or machine learning applications, the Go client provides support for dense vector indexing and k-nearest neighbors (kNN) search. This page uses the [typed API](https://www.elastic.co/elastic/docs-builder/docs/3174/reference/elasticsearch/clients/go/typed-api) with the [`esdsl`](https://www.elastic.co/elastic/docs-builder/docs/3174/reference/elasticsearch/clients/go/typed-api/esdsl) builders. For the full kNN search reference, see [kNN search](https://docs-v3-preview.elastic.dev/elastic/docs-builder/docs/3174/solutions/search/vector/knn) in the Elasticsearch documentation.
```go
import "github.com/elastic/go-elasticsearch/v9/typedapi/esdsl"
```


## Creating an index with dense vector mapping

Before indexing documents with vectors, create an index with the appropriate dense vector mapping. The [`esdsl`](https://www.elastic.co/elastic/docs-builder/docs/3174/reference/elasticsearch/clients/go/typed-api/esdsl) mapping builders provide a concise, fluent syntax:
```go
mappings := esdsl.NewTypeMapping().
    AddProperty("docid", esdsl.NewKeywordProperty()).
    AddProperty("title", esdsl.NewTextProperty()).
    AddProperty("emb", esdsl.NewDenseVectorProperty().
        Dims(1536).
        Index(true).
        Similarity(densevectorsimilarity.Cosine))

res, err := es.Indices.
    Create("my-vectors").
    Mappings(mappings).
    Do(context.Background())
```


## Indexing documents with vectors

The `types.DenseVectorF32` type automatically encodes `[]float32` vectors as base64 strings during JSON serialization, reducing payload size and improving indexing speed:
```go
type Document struct {
    DocID string               `json:"docid"`
    Title string               `json:"title"`
    Emb   types.DenseVectorF32 `json:"emb"`
}

document := Document{
    DocID: "doc1",
    Title: "Example document with vector embedding",
    Emb:   types.DenseVectorF32{0.1, 0.2, 0.3, 0.4, 0.5},
}

res, err := es.Index("my-vectors").
    Document(document).
    Do(context.Background())
```


## Searching with kNN

Once your vectors are indexed, you can perform k-nearest neighbors (kNN) search to find similar documents. The `esdsl` query builders provide a fluent syntax for kNN search:
```go
queryVector := []float32{0.1, 0.2, 0.3, 0.4, 0.5}

res, err := es.Search().
    Index("my-vectors").
    Query(
        esdsl.NewKnnQuery().
            Field("emb").
            QueryVector(queryVector...).
            K(10).
            NumCandidates(100),
    ).
    Do(context.Background())
```


## Performance benefits

Using `types.DenseVectorF32` provides significant performance improvements over standard JSON arrays of floats:
- **Reduced payload size**: base64 encoding is more compact than JSON number arrays
- **Faster parsing**: Eliminates JSON number parsing overhead
- **Improved indexing speed**: Performance gains increase with vector dimensionality and can improve indexing speeds by up to 3x

<note>
  For best performance, use `types.DenseVectorF32` when your vectors are already in `[]float32` format. If you have pre-encoded bytes, use `types.DenseVectorBytes` to avoid re-encoding.
</note>


## Using DenseVectorBytes

If you already have pre-encoded vector bytes from another system, use `types.DenseVectorBytes`:
```go
type Document struct {
    Emb types.DenseVectorBytes `json:"emb"`
}

vectorBytes := []byte{...}
document := Document{
    Emb: types.DenseVectorBytes(vectorBytes),
}

res, err := es.Index("my-vectors").
    Document(document).
    Do(context.Background())
```