Link Search Menu Expand Document Documentation Menu

Go 客户端

OpenSearch Go 客户端允许您将 Go 应用程序连接到 OpenSearch 集群中的数据。本入门指南演示了如何连接到 OpenSearch、索引文档和运行查询。有关客户端的完整 API 文档和更多示例,请参阅Go 客户端 API 文档

有关客户端源代码,请参阅opensearch-go 仓库

设置

如果您要启动一个新项目,请运行以下命令创建一个新模块

go mod init <mymodulename>

要将 Go 客户端添加到您的项目,像导入其他模块一样导入它

go get github.com/opensearch-project/opensearch-go

连接到 OpenSearch

要连接到默认的 OpenSearch 主机,如果您正在使用安全插件,请使用地址 https://:9200 创建一个客户端对象

client, err := opensearch.NewClient(opensearch.Config{
        Transport: &http.Transport{
            TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
        },
        Addresses: []string{"https://:9200"},
        Username:  "admin", // For testing only. Don't store credentials in code.
        Password:  "admin",
    })

如果您没有使用安全插件,请使用地址 https://:9200 创建一个客户端对象

client, err := opensearch.NewClient(opensearch.Config{
        Transport: &http.Transport{
            TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
        },
        Addresses: []string{"https://:9200"},
    })

连接到 Amazon OpenSearch 服务

以下示例演示了连接到 Amazon OpenSearch 服务

package main

import (
	"context"
	"log"

	"github.com/aws/aws-sdk-go-v2/aws"
	"github.com/aws/aws-sdk-go-v2/config"
	opensearch "github.com/opensearch-project/opensearch-go/v4"
	opensearchapi "github.com/opensearch-project/opensearch-go/v4/opensearchapi"
	requestsigner "github.com/opensearch-project/opensearch-go/v4/signer/awsv2"
)

const endpoint = "" // e.g. https://opensearch-domain.region.com or Amazon OpenSearch Serverless endpoint

func main() {
	ctx := context.Background()

	awsCfg, err := config.LoadDefaultConfig(ctx,
		config.WithRegion("<AWS_REGION>"),
		config.WithCredentialsProvider(
			getCredentialProvider("<AWS_ACCESS_KEY>", "<AWS_SECRET_ACCESS_KEY>", "<AWS_SESSION_TOKEN>"),
		),
	)
	if err != nil {
		log.Fatal(err) // Do not log.fatal in a production ready app.
	}

	// Create an AWS request Signer and load AWS configuration using default config folder or env vars.
	signer, err := requestsigner.NewSignerWithService(awsCfg, "es")
	if err != nil {
		log.Fatal(err) // Do not log.fatal in a production ready app.
	}

	// Create an opensearch client and use the request-signer
	client, err := opensearch.NewClient(opensearch.Config{
		Addresses: []string{endpoint},
		Signer:    signer,
	})
	if err != nil {
		log.Fatal("client creation err", err)
	}

	_ = client
	// your code here
}

func getCredentialProvider(accessKey, secretAccessKey, token string) aws.CredentialsProviderFunc {
	return func(ctx context.Context) (aws.Credentials, error) {
		c := &aws.Credentials{
			AccessKeyID:     accessKey,
			SecretAccessKey: secretAccessKey,
			SessionToken:    token,
		}
		return *c, nil
	}
}

连接到 Amazon OpenSearch Serverless

以下示例演示了连接到 Amazon OpenSearch 无服务器服务

package main

import (
	"context"
	"log"

	"github.com/aws/aws-sdk-go-v2/aws"
	"github.com/aws/aws-sdk-go-v2/config"
	opensearch "github.com/opensearch-project/opensearch-go/v4"
	requestsigner "github.com/opensearch-project/opensearch-go/v4/signer/awsv2"
)

const endpoint = "" // e.g. https://opensearch-domain.region.com or Amazon OpenSearch Serverless endpoint

func main() {
	ctx := context.Background()

	awsCfg, err := config.LoadDefaultConfig(ctx,
		config.WithRegion("<AWS_REGION>"),
		config.WithCredentialsProvider(
			getCredentialProvider("<AWS_ACCESS_KEY>", "<AWS_SECRET_ACCESS_KEY>", "<AWS_SESSION_TOKEN>"),
		),
	)
	if err != nil {
		log.Fatal(err) // Do not log.fatal in a production ready app.
	}

	// Create an AWS request Signer and load AWS configuration using default config folder or env vars.
	signer, err := requestsigner.NewSignerWithService(awsCfg, "aoss")
	if err != nil {
		log.Fatal(err) // Do not log.fatal in a production ready app.
	}

	// Create an opensearch client and use the request-signer
	client, err := opensearch.NewClient(opensearch.Config{
		Addresses: []string{endpoint},
		Signer:    signer,
	})
	if err != nil {
		log.Fatal("client creation err", err)
	}

	_ = client
	// your code here
}

func getCredentialProvider(accessKey, secretAccessKey, token string) aws.CredentialsProviderFunc {
	return func(ctx context.Context) (aws.Credentials, error) {
		c := &aws.Credentials{
			AccessKeyID:     accessKey,
			SecretAccessKey: secretAccessKey,
			SessionToken:    token,
		}
	}
}

Go 客户端构造函数接受一个 opensearch.Config{} 类型,可以通过选项(例如 OpenSearch 节点地址列表或用户名和密码组合)进行自定义。

要连接到多个 OpenSearch 节点,请在 Addresses 参数中指定它们

var (
    urls = []string{"https://:9200", "https://:9201", "https://:9202"}
)

client, err := opensearch.NewClient(opensearch.Config{
        Transport: &http.Transport{
            TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
        },
        Addresses: urls,
})

Go 客户端默认最多重试请求三次。要自定义重试次数,请设置 MaxRetries 参数。此外,您可以通过设置 RetryOnStatus 参数来更改要重试请求的响应代码列表。以下代码片段创建了一个具有自定义 MaxRetriesRetryOnStatus 值的新 Go 客户端

client, err := opensearch.NewClient(opensearch.Config{
        Transport: &http.Transport{
            TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
        },
        Addresses: []string{"https://:9200"},
        MaxRetries: 5,
        RetryOnStatus: []int{502, 503, 504},
    })

创建索引

要创建 OpenSearch 索引,请使用 IndicesCreateRequest 方法。您可以使用以下代码构建具有自定义设置的 JSON 对象

settings := strings.NewReader(`{
    'settings': {
        'index': {
            'number_of_shards': 1,
            'number_of_replicas': 0
            }
        }
    }`)

res := opensearchapi.IndicesCreateRequest{
    Index: "go-test-index1",
    Body:  settings,
}

索引文档

您可以使用 IndexRequest 方法将文档索引到 OpenSearch 中

document := strings.NewReader(`{
    "title": "Moneyball",
    "director": "Bennett Miller",
    "year": "2011"
}`)

docId := "1"
req := opensearchapi.IndexRequest{
    Index:      "go-test-index1",
    DocumentID: docId,
    Body:       document,
}
insertResponse, err := req.Do(context.Background(), client)

执行批量操作

您可以使用客户端的 Bulk 方法同时执行多项操作。这些操作可以是相同类型,也可以是不同类型。

blk, err := client.Bulk(
		strings.NewReader(`
    { "index" : { "_index" : "go-test-index1", "_id" : "2" } }
    { "title" : "Interstellar", "director" : "Christopher Nolan", "year" : "2014"}
    { "create" : { "_index" : "go-test-index1", "_id" : "3" } }
    { "title" : "Star Trek Beyond", "director" : "Justin Lin", "year" : "2015"}
    { "update" : {"_id" : "3", "_index" : "go-test-index1" } }
    { "doc" : {"year" : "2016"} }
`),
	)

搜索文档

搜索文档最简单的方法是构建查询字符串。以下代码使用 multi_match 查询在标题和导演字段中搜索“miller”。它提高了“miller”出现在标题字段中的文档的权重

content := strings.NewReader(`{
    "size": 5,
    "query": {
        "multi_match": {
        "query": "miller",
        "fields": ["title^2", "director"]
        }
    }
}`)

search := opensearchapi.SearchRequest{
    Index: []string{"go-test-index1"},
    Body: content,
}

searchResponse, err := search.Do(context.Background(), client)

删除文档

您可以使用 DeleteRequest 方法删除文档

delete := opensearchapi.DeleteRequest{
    Index:      "go-test-index1",
    DocumentID: "1",
}

deleteResponse, err := delete.Do(context.Background(), client)

删除索引

您可以使用 IndicesDeleteRequest 方法删除索引

deleteIndex := opensearchapi.IndicesDeleteRequest{
    Index: []string{"go-test-index1"},
}

deleteIndexResponse, err := deleteIndex.Do(context.Background(), client)

示例程序

以下示例程序创建一个客户端,添加一个具有非默认设置的索引,插入一个文档,执行批量操作,搜索该文档,删除该文档,然后删除该索引

package main
import (
    "os"
    "context"
    "crypto/tls"
    "fmt"
    opensearch "github.com/opensearch-project/opensearch-go"
    opensearchapi "github.com/opensearch-project/opensearch-go/opensearchapi"
    "net/http"
    "strings"
)
const IndexName = "go-test-index1"
func main() {
    // Initialize the client with SSL/TLS enabled.
    client, err := opensearch.NewClient(opensearch.Config{
        Transport: &http.Transport{
            TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
        },
        Addresses: []string{"https://:9200"},
        Username:  "admin", // For testing only. Don't store credentials in code.
        Password:  "admin",
    })
    if err != nil {
        fmt.Println("cannot initialize", err)
        os.Exit(1)
    }

    // Print OpenSearch version information on console.
    fmt.Println(client.Info())

    // Define index settings.
    settings := strings.NewReader(`{
     'settings': {
       'index': {
            'number_of_shards': 1,
            'number_of_replicas': 2
            }
          }
     }`)

    // Create an index with non-default settings.
    res := opensearchapi.IndicesCreateRequest{
        Index: IndexName,
        Body:  settings,
    }
    fmt.Println("Creating index")
    fmt.Println(res)

    // Add a document to the index.
    document := strings.NewReader(`{
        "title": "Moneyball",
        "director": "Bennett Miller",
        "year": "2011"
    }`)

    docId := "1"
    req := opensearchapi.IndexRequest{
        Index:      IndexName,
        DocumentID: docId,
        Body:       document,
    }
    insertResponse, err := req.Do(context.Background(), client)
    if err != nil {
        fmt.Println("failed to insert document ", err)
        os.Exit(1)
    }
    fmt.Println("Inserting a document")
    fmt.Println(insertResponse)
    defer insertResponse.Body.Close()

    // Perform bulk operations.
    blk, err := client.Bulk(
		strings.NewReader(`
    { "index" : { "_index" : "go-test-index1", "_id" : "2" } }
    { "title" : "Interstellar", "director" : "Christopher Nolan", "year" : "2014"}
    { "create" : { "_index" : "go-test-index1", "_id" : "3" } }
    { "title" : "Star Trek Beyond", "director" : "Justin Lin", "year" : "2015"}
    { "update" : {"_id" : "3", "_index" : "go-test-index1" } }
    { "doc" : {"year" : "2016"} }
`),
	)

    if err != nil {
        fmt.Println("failed to perform bulk operations", err)
        os.Exit(1)
    }
    fmt.Println("Performing bulk operations")
    fmt.Println(blk)

    // Search for the document.
    content := strings.NewReader(`{
       "size": 5,
       "query": {
           "multi_match": {
           "query": "miller",
           "fields": ["title^2", "director"]
           }
      }
    }`)

    search := opensearchapi.SearchRequest{
        Index: []string{IndexName},
        Body: content,
    }

    searchResponse, err := search.Do(context.Background(), client)
    if err != nil {
        fmt.Println("failed to search document ", err)
        os.Exit(1)
    }
    fmt.Println("Searching for a document")
    fmt.Println(searchResponse)
    defer searchResponse.Body.Close()

    // Delete the document.
    delete := opensearchapi.DeleteRequest{
        Index:      IndexName,
        DocumentID: docId,
    }

    deleteResponse, err := delete.Do(context.Background(), client)
    if err != nil {
        fmt.Println("failed to delete document ", err)
        os.Exit(1)
    }
    fmt.Println("Deleting a document")
    fmt.Println(deleteResponse)
    defer deleteResponse.Body.Close()

    // Delete the previously created index.
    deleteIndex := opensearchapi.IndicesDeleteRequest{
        Index: []string{IndexName},
    }

    deleteIndexResponse, err := deleteIndex.Do(context.Background(), client)
    if err != nil {
        fmt.Println("failed to delete index ", err)
        os.Exit(1)
    }
    fmt.Println("Deleting the index")
    fmt.Println(deleteIndexResponse)
    defer deleteIndexResponse.Body.Close()
}