go操作es

安装依赖

安装客户端

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
// ES 配置
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
// createIndex 创建索引
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 数据对应的 ReviewTag 结构体,分别表示”评价”和”评价标签”。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
// Review 评价数据
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"`
}

// Tag 评价标签
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
// indexDocument 索引文档
func indexDocument(client *elasticsearch.TypedClient) {
// 定义 document 结构体对象
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
// getDocument 获取文档
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"
)

// searchDocument 搜索所有文档
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"
)

// searchDocument2 指定条件搜索文档
func searchDocument2(client *elasticsearch.TypedClient) {
// 搜索content中包含好评的文档
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"
)

// aggregationDemo 聚合
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": { // 将所有文档的 score 的平均值聚合为 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
// updateDocument 更新文档
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
// updateDocument2 更新文档
func updateDocument2(client *elasticsearch.TypedClient) {
// 修改后的JSON字符串
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"
}`
// 直接使用JSON字符串更新
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
// deleteDocument 删除 document
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
// deleteIndex 删除 index
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)
}


go操作es
http://example.com/2024/04/11/elasticsearch/go操作/
作者
Mrxiad
发布于
2024年4月11日
许可协议