﻿---
title: Examples
description: This sections lists a series of frequent use cases that will help you start with this new API. Creating an index, Indexing a document, Bulk indexing,...
url: https://www.elastic.co/elastic/docs-builder/docs/2689/reference/elasticsearch/clients/go/examples
products:
  - Elasticsearch
  - Elasticsearch Client
  - Elasticsearch Go Client
---

# Examples
This sections lists a series of frequent use cases that will help you start with this new API.
- [Creating an index](#indices)
- [Indexing a document](#indexing)
- [Bulk indexing](#bulk)
- [Retrieving a document](#retrieving_document)
- [Search](#search)
- [Aggregations](#aggregations)
- [Indexing dense vectors](#dense_vectors)

<note>
  This is a work in progress, the documentation will evolve in the future.
</note>


## Creating an index

For this example on how to create an index, lets create an index named `test-index` and provide a mapping for the field `price` which will be an integer. Notice how using the builder for the `IntegerNumberProperty` will automatically apply the correct value for the `type` field.
```go
res, err := es.Indices.Create("test-index").
    Request(&create.Request{
        Mappings: &types.TypeMapping{
            Properties: map[string]types.Property{
                "price": types.NewIntegerNumberProperty(),
            },
        },
    }).
    Do(nil)
```


## Indexing a document

The standard way of indexing a document is to provide a `struct` to the `Request` method, the standard `json/encoder` will be run on your structure and the result will be sent to Elasticsearch.
```go
document := struct {
    Id    int    `json:"id"`
    Name  string `json:"name"`
    Price int    `json:"price"`
}{
    Id:    1,
    Name:  "Foo",
    Price: 10,
}

res, err := es.Index("index_name").
    Request(document).
    Do(context.Background())
```

Alternatively, you can use the `Raw` method and provide the already serialized JSON:
```go
res, err := es.Index("index_name").
            Raw([]byte(`{
              "id": 1,
              "name": "Foo",
              "price": 10
            }`)).Do(context.Background())
```


## Bulk indexing

When ingesting many documents, use the Bulk API to send multiple operations in a single request.
With the typed client, you can build a bulk request by appending operations and then executing it:
```go
index := "my-index"
id1 := "1"
id2 := "2"

bulk := es.Bulk()
if err := bulk.IndexOp(
    types.IndexOperation{Index_: &index, Id_: &id1},
    map[string]any{"title": "Test 1"},
); err != nil {
    // Handle error.
}

if err := bulk.IndexOp(
    types.IndexOperation{Index_: &index, Id_: &id2},
    map[string]any{"title": "Test 2"},
); err != nil {
    // Handle error.
}

res, err := bulk.Do(context.Background())
if err != nil {
    // Handle error.
}
if res.Errors {
    // One or more operations failed.
}
```

The client repository also contains complete, runnable examples for bulk ingestion (manual NDJSON, `esutil.BulkIndexer`, typed bulk, benchmarks, Kafka ingestion): [`_examples/bulk`](https://github.com/elastic/go-elasticsearch/tree/master/_examples/bulk).
If you prefer the classic client (NDJSON + `Bulk()`), you can build the NDJSON payload yourself and submit it with `Bulk()`:
```go
client, err := elasticsearch.NewDefaultClient()
if err != nil {
    // Handle error.
}
defer func() {
    if err := client.Close(context.Background()); err != nil {
        // Handle error.
    }
}()

var buf bytes.Buffer
buf.WriteString(`{ "index" : { "_index" : "test", "_id" : "1" } }` + "\n")
buf.WriteString(`{ "title" : "Test" }` + "\n")

res, err := client.Bulk(bytes.NewReader(buf.Bytes()))
if err != nil {
    // Handle error.
}
defer res.Body.Close()
```

For a higher-level API that takes care of batching, flushing, and concurrency, use the `esutil.BulkIndexer` helper.
The BulkIndexer is designed to be **long-lived**: create it once, keep adding items over time (potentially from multiple goroutines), and call `Close()` once when you are done (for example with `defer`).
```go
client, err := elasticsearch.NewDefaultClient()
if err != nil {
    // Handle error.
}
defer func() {
    if err := client.Close(context.Background()); err != nil {
        // Handle error.
    }
}()

ctx := context.Background()
indexer, err := esutil.NewBulkIndexer(esutil.BulkIndexerConfig{
    Client:     client,
    Index:      "test",
    NumWorkers: 4,
    FlushBytes: 5_000_000,
})
if err != nil {
    // Handle error.
}

defer func() {
    if err := indexer.Close(ctx); err != nil {
        // Handle error.
    }
}()

_ = indexer.Add(ctx, esutil.BulkIndexerItem{
    Action:     "index",
    DocumentID: "1",
    Body:       strings.NewReader(`{"title":"Test"}`),
})
```


## Retrieving a document

Retrieving a document follows the API as part of the argument of the endpoint. In order you provide the `index`, the `id` and then run the query:
```go
res, err := es.Get("index_name", "doc_id").Do(context.Background())
```


## Checking for a document existence

If you do not wish to retrieve the content of the document and want only to check if it exists in your index, we provide the `IsSuccess` shortcut:
```go
if exists, err := es.Exists("index_name", "doc_id").IsSuccess(nil); exists {
    // The document exists !
} else if err != nil {
   // Handle error.
}
```

Result is `true` if everything succeeds, `false` if the document doesn't exist. If an error occurs during the request, you will be granted with a `false` and the relevant error.

## Search

Building a search query can be done with structs or builder. As an example, let's search for a document with a field `name` with a value of `Foo` in the index named `index_name`.
With a struct request:
```go
res, err := es.Search().
    Index("index_name"). 
    Request(&search.Request{ 
        Query: &types.Query{
            Match: map[string]types.MatchQuery{
                "name": {Query: "Foo"}, 
            },
        },
    }).Do(context.Background()) 
```

It produces the following JSON:
```json
{
  "query": {
    "match": {
      "name": {
        "query": "Foo"
      }
    }
  }
}
```


## Aggregations

Given documents with a `price` field, we run a sum aggregation on `index_name`:
```go
totalPricesAgg, err := es.Search().
    Index("index_name"). 
    Request(
        &search.Request{
            Size: some.Int(0), 
            Aggregations: map[string]types.Aggregations{
                "total_prices": { 
                    Sum: &types.SumAggregation{
                        Field: some.String("price"), 
                    },
                },
            },
        },
    ).Do(context.Background())
```


## Indexing dense vectors

<applies-to>
  - Elastic Stack: Generally available since 9.3
</applies-to>

When working with vector embeddings for semantic search or machine learning applications, the typed API provides specialized types for encoding dense vectors that can significantly improve indexing performance.

### Using DenseVectorF32 for optimized indexing

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").
    Request(document).
    Do(context.Background())
```


### Creating an index with dense vector mapping

Before indexing documents with vectors, create an index with the appropriate dense vector mapping:
```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())
```


### Searching with kNN

Once your vectors are indexed, you can perform k-nearest neighbors (kNN) search to find similar documents:
```go
queryVector := []float32{0.1, 0.2, 0.3, 0.4, 0.5} 

res, err := es.Search().
    Index("my-vectors").
    Request(&search.Request{
        Query: esdsl.NewKnnQuery(). 
            Field("emb"). 
            QueryVector(queryVector...). 
            K(10). 
            NumCandidates(100). 
            QueryCaster(),
    }).
    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").
    Request(document).
    Do(context.Background())
```