Go Backend Integration

Series: Elasticsearch 101 | Article: 06


Overview

The official Go client for Elasticsearch is github.com/elastic/go-elasticsearch/v9. It offers two API styles: a low-level client that works with raw JSON and an HTTP-level DSL, and a typed API (added in v8) that provides fully generated Go types for every request and response.

This article uses the typed API. It removes the guesswork from query construction and makes IDE completion actually useful when building complex queries.


Setup

go mod init github.com/yourhandle/articles-api
go get github.com/elastic/go-elasticsearch/v9@latest

Verify the import resolves:

go list -m github.com/elastic/go-elasticsearch/v9

Client Initialization

package elastic

import (
    "github.com/elastic/go-elasticsearch/v9"
)

// NewClient creates a typed Elasticsearch client.
// In production, addresses and credentials come from environment variables.
func NewClient(address, username, password string) (*elasticsearch.TypedClient, error) {
    cfg := elasticsearch.Config{
        Addresses: []string{address},
        Username:  username,
        Password:  password,
    }
    return elasticsearch.NewTypedClient(cfg)
}

TypedClient wraps all APIs with generated request/response structs. You never need to manually marshal JSON for standard operations.

For production with API key authentication (preferred over username/password):


Index Creation

Define the mapping as a Go struct using the types package, then create the index:


Document Types

Define Go structs that represent the document shape. These align exactly with the mapping:


Indexing a Single Document

The typed client handles JSON serialization. Pass the struct directly.


Bulk Indexing

For ingesting or synchronizing large sets of documents, use the BulkIndexer helper from esutil:

The BulkIndexer batches requests internally. The OnFailure callback is critical — failed individual documents do not cause the overall Close to return an error, so you must handle them explicitly.


Searching Documents

Build a typed search request. The following implements a paginated full-text search with filter and aggregation:


HTTP Handler Example

Wire the search function into an HTTP handler. I use the standard library net/http with encoding/json:


Deleting a Document


Partial Update


Error Handling Pattern

The typed client returns typed errors. Check for *types.ElasticsearchError to distinguish Elasticsearch-level errors (like index not found or document already exists) from transport errors:


Summary

  • Use elasticsearch.NewTypedClient for full type safety on request/response structs.

  • Store the client as a dependency; initialize it once at application startup.

  • Pass struct values directly to .Request() — the client handles JSON serialization.

  • Use esutil.BulkIndexer for batch operations; always handle OnFailure.

  • Parse aggregation results via type assertions on res.Aggregations[name].

  • Use errors.As with *types.ElasticsearchError for structured error handling.


Previous: Aggregations and Analytics | Next: React Frontend Integration

Last updated