下面是对Elastic开发的官方Go语言ElasticSearch客户端的综述
这是Go Advent Calendar 2020第八天的文章。
最近在工作中有机会使用ElasticSearch,并在那时发现其官方支持的Go客户端缺乏详细的日本语信息,因此我决定趁此机会整理一下。
go-elasticsearch是一个在GitHub上的项目,位于https://github.com/elastic/go-elasticsearch。
总结
这个官方库是在2019年发布的相对较新的库,已经被认可并维护为Elastic的官方客户端。
https://www.elastic.co/guide/en/elasticsearch/client/index.html
go-elasticsearch客户端有6系和7系两个版本,分别对应Elasticsearch的6系和7系版本。因此,请根据您使用的Elasticsearch版本确定要使用的库的版本。
使用方法
客户创立
在创建客户端时,有两种选择。首先是NewDefaultClient。这个选项不需要参数,但可以通过将ElasticSearch的终端URL放入名为ELASTICSEARCH_URL的环境变量中来自动进行配置。
elasticsearch.NewDefaultClient()
elasticsearch.NewClient(Config)是创建具有各种选项的客户端的方法。当使用Elastic Cloud等服务时,可以使用ID而不是地址进行连接。在这种情况下,忽略了设置在ELASTICSEARCH_URL环境变量中的值。可以包含诸如CACert用于证书和RetryOnStatus用于定义需要重试的状态等选项。
cert, _ := ioutil.ReadFile("path/to/ca.crt")
cfg := elasticsearch.Config{
Addresses: []string{
"http://localhost:9200",
"http://localhost:9201",
},
Username: "foo",
Password: "bar",
RetryOnStatus: []int{429, 502, 503, 504},
CACert: cert,
Transport: &http.Transport{
MaxIdleConnsPerHost: 10,
ResponseHeaderTimeout: time.Second,
DialContext: (&net.Dialer{Timeout: time.Second}).DialContext,
TLSClientConfig: &tls.Config{
MinVersion: tls.VersionTLS11,
},
},
}
elasticsearch.NewClient(cfg)
搜索
在使用搜索引擎的搜索建议等功能时,请按照以下方式使用搜索功能。
var buf bytes.Buffer
query := map[string]interface{}{
"query": map[string]interface{}{
"match": map[string]interface{}{
"title": "test",
},
},
}
if err := json.NewEncoder(&buf).Encode(query); err != nil {
log.Fatalf("Error encoding query: %s", err)
}
// Perform the search request.
res, err = es.Search(
es.Search.WithContext(context.Background()),
es.Search.WithIndex("test"),
es.Search.WithBody(&buf),
es.Search.WithTrackTotalHits(true),
es.Search.WithPretty(),
)
if err != nil {
log.Fatalf("Error getting response: %s", err)
}
defer res.Body.Close()
if res.IsError() {
var e map[string]interface{}
if err := json.NewDecoder(res.Body).Decode(&e); err != nil {
log.Fatalf("Error parsing the response body: %s", err)
} else {
// Print the response status and error information.
log.Fatalf("[%s] %s: %s",
res.Status(),
e["error"].(map[string]interface{})["type"],
e["error"].(map[string]interface{})["reason"],
)
}
}
請參考實際的請求中投遞的Json結構體, 使用map[string]interface{}定義,然後將要搜索的字串放入其中。
发送HTTP请求时的JsonBody如果是这样的
{
"size": 5,
"query": {
"bool": {
"should": [{
"match": {
"word.autocomplete": {
"query": "え"
}
}
}, {
"match": {
"word.readingform": {
"query": "え",
"fuzziness": "AUTO",
"operator": "and"
}
}
}]
}
},
}'
用Go语言定义的查询通常就像这样。它确实相当复杂呢……。
query := map[string]interface{}{
"query": map[string]interface{}{
"bool": map[string]interface{}{
"should": []map[string]interface{}{
{
"match": map[string]interface{}{
"word.autocomplete": map[string]interface{}{
"query": normalized,
},
},
},
{
"match": map[string]interface{}{
"word.readingform": map[string]interface{}{
"query": normalized,
"fuzziness": "AUTO",
"operator": "and",
},
},
},
},
},
},
}
然后将其编码为JSON,并将其放入WithBody参数中的Search方法的参数中,并调用Search方法。
if err := json.NewEncoder(&buf).Encode(query); err != nil {
log.Fatalf("Error encoding query: %s", err)
}
// Perform the search request.
res, err = es.Search(
es.Search.WithContext(context.Background()),
es.Search.WithIndex("test"),
es.Search.WithBody(&buf),
es.Search.WithTrackTotalHits(true),
es.Search.WithPretty(),
)
可以看出还有许多其他的参数。 使用withSort等可以实现排序等功能。
Search方法的响应似乎是对http.Response进行包装的。另外,可以使用IsError()方法来判断是否发生了500错误等。
不像Search等,Index和Create、Update可以相对简单地进行编写。基本上,go-elastic的esapi包中为每个请求准备了名为XXRequest的类型,因此只需将请求的值放入其中,并调用Do方法执行即可。
请在这里对IsError的响应进行检查。
tag := Sample{
ID: id,
Name: name,
}
reqByte, err := json.Marshal(tag)
if err != nil {
return err
}
requestReader := bytes.NewReader(reqByte)
req := esapi.CreateRequest{
Body: requestReader,
Pretty: true,
}
res, err := req.Do(ctx, r.client)
if err != nil {
return xerrors.Errorf("failed to update with elastic search. %w", err)
}
if res.IsError() {
return xerrors.Errorf("failed to update with elastic search. Not ok. %s", res.Status())
}
defer res.Body.Close()
在该类型中,您还可以定义各种选项。让我们试试看UpdateRequest类型。它通常将基本请求的主体存储在Body中,但是我们可以看到可以定义各种选项,如Header和Pretty等。
type UpdateRequest struct {
Index string
DocumentType string
DocumentID string
Body io.Reader
Fields []string
IfPrimaryTerm *int
IfSeqNo *int
Lang string
Parent string
Refresh string
RetryOnConflict *int
Routing string
Source []string
SourceExcludes []string
SourceIncludes []string
Timeout time.Duration
Version *int
VersionType string
WaitForActiveShards string
Pretty bool
Human bool
ErrorTrace bool
FilterPath []string
Header http.Header
ctx context.Context
}
这是ElasticSearch的Go客户端介绍,由Elastic提供支持。
虽然代码可能有点多,但由于官方提供维护,所以可以放心使用,不会有任何损失。