安装依赖
安装客户端
1
| go get github.com/elastic/go-elasticsearch/v8@latest
|
导入依赖
1
| import "github.com/elastic/go-elasticsearch/v8"
|
可以根据实际需求导入不同的客户端版本,也支持在一个项目中导入不同的客户端版本。
1 2 3 4 5 6 7 8
| import ( elasticsearch7 "github.com/elastic/go-elasticsearch/v7" elasticsearch8 "github.com/elastic/go-elasticsearch/v8" )
es7, _ := elasticsearch7.NewDefaultClient() es8, _ := elasticsearch8.NewDefaultClient()
|
连接 ES
1 2 3 4 5 6 7 8 9 10 11 12 13
| cfg := elasticsearch.Config{ Addresses: []string{ "http://localhost:9200", }, }
client, err := elasticsearch.NewTypedClient(cfg) if err != nil { fmt.Printf("elasticsearch.NewTypedClient failed, err:%v\n", err) return }
|
操作
创建 index
建一个名为 my-review-1 的 index。
1 2 3 4 5 6 7 8 9 10 11
| func createIndex(client *elasticsearch.TypedClient) { resp, err := client.Indices. Create("my-review-1"). Do(context.Background()) if err != nil { fmt.Printf("create index failed, err:%v\n", err) return } fmt.Printf("index:%#v\n", resp.Index) }
|
索引 document
定义与 document 数据对应的 Review 和 Tag 结构体,分别表示”评价”和”评价标签”。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| type Review struct { ID int64 `json:"id"` UserID int64 `json:"userID"` Score uint8 `json:"score"` Content string `json:"content"` Tags []Tag `json:"tags"` Status int `json:"status"` PublishTime time.Time `json:"publishDate"` }
type Tag struct { Code int `json:"code"` Title string `json:"title"` }
|
创建一条 document 并添加到 my-review-1 的 index 中。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
| func indexDocument(client *elasticsearch.TypedClient) { d1 := Review{ ID: 1, UserID: 147982601, Score: 5, Content: "这是一个好评!", Tags: []Tag{ {1000, "好评"}, {1100, "物超所值"}, {9000, "有图"}, }, Status: 2, PublishTime: time.Now(), }
resp, err := client.Index("my-review-1"). Id(strconv.FormatInt(d1.ID, 10)). Document(d1). Do(context.Background()) if err != nil { fmt.Printf("indexing document failed, err:%v\n", err) return } fmt.Printf("result:%#v\n", resp.Result) }
|
获取 document
根据 id 获取 document。
1 2 3 4 5 6 7 8 9 10
| func getDocument(client *elasticsearch.TypedClient, id string) { resp, err := client.Get("my-review-1", id). Do(context.Background()) if err != nil { fmt.Printf("get document by id failed, err:%v\n", err) return } fmt.Printf("fileds:%s\n", resp.Source_) }
|
检索 document
构建搜索查询可以使用结构化的查询条件。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
| import ( "context" "fmt" "github.com/elastic/go-elasticsearch/v8" "github.com/elastic/go-elasticsearch/v8/typedapi/types" )
func searchDocument(client *elasticsearch.TypedClient) { resp, err := client.Search(). Index("my-review-1"). Query(&types.Query{ MatchAll: &types.MatchAllQuery{}, }). Do(context.Background()) if err != nil { fmt.Printf("search document failed, err:%v\n", err) return } fmt.Printf("total: %d\n", resp.Hits.Total.Value) for _, hit := range resp.Hits.Hits { fmt.Printf("%s\n", hit.Source_) } }
|
下面是在 my-review-1 中搜索 content 包含 “好评” 的文档。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
| import ( "context" "fmt" "github.com/elastic/go-elasticsearch/v8" "github.com/elastic/go-elasticsearch/v8/typedapi/types" )
func searchDocument2(client *elasticsearch.TypedClient) { resp, err := client.Search(). Index("my-review-1"). Query(&types.Query{ MatchPhrase: map[string]types.MatchPhraseQuery{ "content": {Query: "好评"}, }, }). Do(context.Background()) if err != nil { fmt.Printf("search document failed, err:%v\n", err) return } fmt.Printf("total: %d\n", resp.Hits.Total.Value) for _, hit := range resp.Hits.Hits { fmt.Printf("%s\n", hit.Source_) } }
|
聚合
在 my-review-1 上运行一个平均值聚合,得到所有文档 score 的平均值。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
| import ( "context" "fmt" "github.com/elastic/go-elasticsearch/v8" "github.com/elastic/go-elasticsearch/v8/typedapi/core/search" "github.com/elastic/go-elasticsearch/v8/typedapi/some" "github.com/elastic/go-elasticsearch/v8/typedapi/types" )
func aggregationDemo(client *elasticsearch.TypedClient) { avgScoreAgg, err := client.Search(). Index("my-review-1"). Request( &search.Request{ Size: some.Int(0), Aggregations: map[string]types.Aggregations{ "avg_score": { Avg: &types.AverageAggregation{ Field: some.String("score"), }, }, }, }, ).Do(context.Background()) if err != nil { fmt.Printf("aggregation failed, err:%v\n", err) return } fmt.Printf("avgScore:%#v\n", avgScoreAgg.Aggregations["avg_score"]) }
|
更新 document
使用新值更新文档。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
| func updateDocument(client *elasticsearch.TypedClient) { d1 := Review{ ID: 1, UserID: 147982601, Score: 5, Content: "这是一个修改后的好评!", Tags: []Tag{ {1000, "好评"}, {9000, "有图"}, }, Status: 2, PublishTime: time.Now(), }
resp, err := client.Update("my-review-1", "1"). Doc(d1). Do(context.Background()) if err != nil { fmt.Printf("update document failed, err:%v\n", err) return } fmt.Printf("result:%v\n", resp.Result) }
|
更新可以使用结构体变量也可以使用原始JSON字符串数据。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33
| func updateDocument2(client *elasticsearch.TypedClient) { str := `{ "id":1, "userID":147982601, "score":5, "content":"这是一个二次修改后的好评!", "tags":[ { "code":1000, "title":"好评" }, { "code":9000, "title":"有图" } ], "status":2, "publishDate":"2023-12-10T15:27:18.219385+08:00" }` resp, err := client.Update("my-review-1", "1"). Request(&update.Request{ Doc: json.RawMessage(str), }). Do(context.Background()) if err != nil { fmt.Printf("update document failed, err:%v\n", err) return } fmt.Printf("result:%v\n", resp.Result) }
|
删除 document
根据文档 id 删除文档。
1 2 3 4 5 6 7 8 9 10
| func deleteDocument(client *elasticsearch.TypedClient) { resp, err := client.Delete("my-review-1", "1"). Do(context.Background()) if err != nil { fmt.Printf("delete document failed, err:%v\n", err) return } fmt.Printf("result:%v\n", resp.Result) }
|
删除 index
1 2 3 4 5 6 7 8 9 10 11 12
| func deleteIndex(client *elasticsearch.TypedClient) { resp, err := client.Indices. Delete("my-review-1"). Do(context.Background()) if err != nil { fmt.Printf("delete document failed, err:%v\n", err) return } fmt.Printf("Acknowledged:%v\n", resp.Acknoledged) }
|