Go Client for OpenSearch
See the codeOpenSearch Go Client
opensearch-go is a community-driven, open source fork of go-elasticsearch licensed under the Apache v2.0 License. For more information, see opensearch.org.
The client supports automatic node discovery, request-based connection routing, and role-aware node selection. See the User Guide and guides for usage examples and configuration options.
Upgrading across a major version? The osapilint tool automates most of the API-shape changes (type, method, and field renames) across the v2 -> v5 hops - see cmd/osapilint/README.md and the per-version deep-dives (v3 -> v4, v4 -> v5).
Install the client:
go get github.com/opensearch-project/opensearch-go/v5
A small CRUD example - create an index, index a document, read it back, search for it, then delete it:
package main
import (
"context"
"fmt"
"log"
"strings"
"github.com/opensearch-project/opensearch-go/v5"
"github.com/opensearch-project/opensearch-go/v5/opensearchapi"
)
func main() {
client, err := opensearchapi.NewClient(opensearchapi.Config{
Client: opensearch.Config{
Addresses: []string{"https://localhost:9200"},
Username: "admin",
Password: "myStrongPassword123!",
},
})
if err != nil {
log.Fatal(err)
}
ctx := context.Background()
// Create an index.
if _, err = client.Indices.Create(ctx, opensearchapi.IndicesCreateReq{
Index: "movies",
BodyReader: strings.NewReader(`{"settings": {"number_of_shards": 1}}`),
}); err != nil {
log.Fatal(err)
}
// Index two documents. Omitting ID lets OpenSearch generate one, returned as
// resp.ID. This keeps the example simple, but in production prefer a
// client-supplied ID derived from your data's natural key: it makes indexing
// idempotent (a retry overwrites rather than duplicates) and lets you address
// the document later without storing the server's ID. Refresh=true makes the
// documents immediately searchable, which is convenient here but hurts
// indexing throughput at scale - prefer the default refresh in production.
movies := []string{
`{"title": "WarGames", "year": 1983}`,
`{"title": "Sneakers", "year": 1992}`,
}
var ids []string
for _, doc := range movies {
indexed, err := client.Doc.Index(ctx, opensearchapi.IndexReq{
Index: "movies",
Body: strings.NewReader(doc),
Params: &opensearchapi.IndexParams{Refresh: "true"},
})
if err != nil {
log.Fatal(err)
}
ids = append(ids, indexed.ID)
}
// Get the first document back by its generated ID.
got, err := client.Doc.Get(ctx, opensearchapi.GetReq{Index: "movies", ID: ids[0]})
if err != nil {
log.Fatal(err)
}
fmt.Printf("get id=%s found=%v source=%q\n", got.ID, got.Found, got.Source)
// Search for WarGames; with two documents indexed, this confirms we get the
// right one back rather than just "a" result.
search, err := client.Search(ctx, &opensearchapi.SearchReq{
Indices: []string{"movies"},
BodyReader: strings.NewReader(`{"query": {"match": {"title": "WarGames"}}}`),
})
if err != nil {
log.Fatal(err)
}
fmt.Printf("%d hit(s)\n", len(search.Hits.Hits))
for _, hit := range search.Hits.Hits {
fmt.Printf(" source=%q\n", hit.Source)
}
// Delete both documents.
for _, id := range ids {
if _, err = client.Doc.Delete(ctx, opensearchapi.DeleteReq{Index: "movies", ID: id}); err != nil {
log.Fatal(err)
}
}
}
Next steps:
OPENSEARCH_GO_* runtime override.opensearchapi usage README - client creation, requests, responses, query parameters, and partial-failure errors.OPENSEARCH_GO_LOG=debug prints the client's internal records to stderr. To route log messages, configure a log-zerolog or log-slog logger. See Cost for additional recommendations.osapilint)This project has adopted the Amazon Open Source Code of Conduct. For more information see the Code of Conduct FAQ, or contact opensource-codeofconduct@amazon.com with any additional questions or comments.
This project is licensed under the Apache v2.0 License.
Copyright OpenSearch Contributors. See NOTICE for details.
Overall
Maintained
Code review
Latest release
Releases this year
5 followers · starred Aug 2026
19 followers · starred Feb 2024
46 followers · starred Sep 2024
38 followers · starred Jun 2022
Go Client for OpenSearch
See the codeOpenSearch Go Client
opensearch-go is a community-driven, open source fork of go-elasticsearch licensed under the Apache v2.0 License. For more information, see opensearch.org.
The client supports automatic node discovery, request-based connection routing, and role-aware node selection. See the User Guide and guides for usage examples and configuration options.
Upgrading across a major version? The osapilint tool automates most of the API-shape changes (type, method, and field renames) across the v2 -> v5 hops - see cmd/osapilint/README.md and the per-version deep-dives (v3 -> v4, v4 -> v5).
Install the client:
go get github.com/opensearch-project/opensearch-go/v5
A small CRUD example - create an index, index a document, read it back, search for it, then delete it:
package main
import (
"context"
"fmt"
"log"
"strings"
"github.com/opensearch-project/opensearch-go/v5"
"github.com/opensearch-project/opensearch-go/v5/opensearchapi"
)
func main() {
client, err := opensearchapi.NewClient(opensearchapi.Config{
Client: opensearch.Config{
Addresses: []string{"https://localhost:9200"},
Username: "admin",
Password: "myStrongPassword123!",
},
})
if err != nil {
log.Fatal(err)
}
ctx := context.Background()
// Create an index.
if _, err = client.Indices.Create(ctx, opensearchapi.IndicesCreateReq{
Index: "movies",
BodyReader: strings.NewReader(`{"settings": {"number_of_shards": 1}}`),
}); err != nil {
log.Fatal(err)
}
// Index two documents. Omitting ID lets OpenSearch generate one, returned as
// resp.ID. This keeps the example simple, but in production prefer a
// client-supplied ID derived from your data's natural key: it makes indexing
// idempotent (a retry overwrites rather than duplicates) and lets you address
// the document later without storing the server's ID. Refresh=true makes the
// documents immediately searchable, which is convenient here but hurts
// indexing throughput at scale - prefer the default refresh in production.
movies := []string{
`{"title": "WarGames", "year": 1983}`,
`{"title": "Sneakers", "year": 1992}`,
}
var ids []string
for _, doc := range movies {
indexed, err := client.Doc.Index(ctx, opensearchapi.IndexReq{
Index: "movies",
Body: strings.NewReader(doc),
Params: &opensearchapi.IndexParams{Refresh: "true"},
})
if err != nil {
log.Fatal(err)
}
ids = append(ids, indexed.ID)
}
// Get the first document back by its generated ID.
got, err := client.Doc.Get(ctx, opensearchapi.GetReq{Index: "movies", ID: ids[0]})
if err != nil {
log.Fatal(err)
}
fmt.Printf("get id=%s found=%v source=%q\n", got.ID, got.Found, got.Source)
// Search for WarGames; with two documents indexed, this confirms we get the
// right one back rather than just "a" result.
search, err := client.Search(ctx, &opensearchapi.SearchReq{
Indices: []string{"movies"},
BodyReader: strings.NewReader(`{"query": {"match": {"title": "WarGames"}}}`),
})
if err != nil {
log.Fatal(err)
}
fmt.Printf("%d hit(s)\n", len(search.Hits.Hits))
for _, hit := range search.Hits.Hits {
fmt.Printf(" source=%q\n", hit.Source)
}
// Delete both documents.
for _, id := range ids {
if _, err = client.Doc.Delete(ctx, opensearchapi.DeleteReq{Index: "movies", ID: id}); err != nil {
log.Fatal(err)
}
}
}
Next steps:
OPENSEARCH_GO_* runtime override.opensearchapi usage README - client creation, requests, responses, query parameters, and partial-failure errors.OPENSEARCH_GO_LOG=debug prints the client's internal records to stderr. To route log messages, configure a log-zerolog or log-slog logger. See Cost for additional recommendations.osapilint)This project has adopted the Amazon Open Source Code of Conduct. For more information see the Code of Conduct FAQ, or contact opensource-codeofconduct@amazon.com with any additional questions or comments.
This project is licensed under the Apache v2.0 License.
Copyright OpenSearch Contributors. See NOTICE for details.
Overall
Maintained
Code review
Latest release
Releases this year
5 followers · starred Aug 2026
19 followers · starred Feb 2024
46 followers · starred Sep 2024
38 followers · starred Jun 2022