elasticSearch总结

ES

es是什么

elasticSearch是一个开源的分布式搜索引擎。es提供了接近实时的搜索以及强大的搜索能力,可扩展性好。

使用docker-compose搭建es集群

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
version: "3.7"

services:
elasticsearch:
container_name: elasticsearch
image: docker.elastic.co/elasticsearch/elasticsearch:8.9.1
environment:
- node.name=elasticsearch
- ES_JAVA_OPTS=-Xms512m -Xmx512m
- discovery.type=single-node
- xpack.security.enabled=false
ports:
- 9200:9200
- 9300:9300
networks:
- elastic
kibana:
image: docker.elastic.co/kibana/kibana:8.9.1
container_name: kibana
ports:
- 5601:5601
networks:
- elastic
depends_on:
- elasticsearch

networks:
elastic:

基本数据类型

  • index: es对逻辑数据的逻辑存储,可以将index作为关系型数据库的表

  • document:相当于关系型数据的一行数据,document由多个字段构成

  • mapping:所有文档写进索引之前都会先进行分析,如何将输入的文本分割为词条、哪些词条又会被过滤,这种行为叫做 映射(mapping)。一般由用户自己定义规则。

  • 索引是文档的逻辑分组,类似于数据库中的表

  • 分片是索引的物理分区,用于提高数据分布和查询效率

  • 节点是运行es的服务器实例

工作原理

  1. 接受用户的查询请求:es通过restful api 或者是 josn请求接受用户的查询请求
  2. 路由匹配:接收到查询请求后,es根据请求中的索引和分片信息请求路由到相应的节点
  3. 执行查询:节点执行查询请求,并在相应的索引中查找匹配的文档
  4. 返回查询结果:查询结果以json格式返回给用户,包括匹配的文档和相关的字段信息

基本api的使用

检查健康状态

dev console中

1
get _cat/health?v

本地cmd中

1
curl -X GET "127.0.0.1:9200/_cat/health?v"

索引

创建索引
1
PUT /my-index

在创建索引时还可以指定以下内容:

  • 索引的设置(setting)
  • 索引中字段的映射(mapping)
  • 索引别名(alias)

例如

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
34
35
36
37
38
39
40
41
42
PUT /review-1
{
"settings": {
"number_of_replicas": 1
},
"mappings": {
"properties": {
"id":{
"type": "long"
},
"userID":{
"type": "long"
},
"score":{
"type": "integer"
},
"status":{
"type": "integer"
},
"content":{
"type": "text"
},
"publishTime":{
"type": "date"
},
"tags":{
"type": "nested",
"properties": {
"code":{
"type": "keyword"
},
"title":{
"type": "text"
}
}
}
}
},
"aliases": {
"review_1": {}
}
}
删除索引
1
DELETE /my-index

文档

创建文档
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
POST /review-1/_create/1
{
"id":1,
"userID":147982601,
"score":5,
"status":2,
"publishTime":"2023-09-09T16:07:42.499144+08:00",
"content":"这是一个好评!",
"tags":[
{
"code":1000,
"title":"好评"
},
{
"code":2000,
"title":"物超所值"
},
{
"code":3000,
"title":"有图"
}
]
}
判断文档是否存在
1
HEAD /review-1/_doc/1
获取文档
1
GET /review-1/_doc/1
获取数据
1
GET /review-1/_source/1
返回指定字段
1
GET /review-1/_source/1?_source=content,score

批量获取文档

1
2
GET /_mget
GET /index/_mget
1
2
3
4
5
6
7
8
9
10
11
GET /review-1/_mget
{
"docs":[
{
"_id":"1"
},
{
"_id":"2"
}
]
}
删除文档
1
DELETE /review-1/_doc/1
更新文档
1
2
3
4
5
6
POST /review-1/_update/1
{
"doc": {
"content": "这是修改过的好评!"
}
}

go-elasticsearc包的使用

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
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
package main

import (
"context"
"fmt"
"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"
"time"

"github.com/elastic/go-elasticsearch/v8"
"github.com/spf13/cast"
)

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:"publishTime"`
}

type Tag struct {
Code int `json:"code"`
Title string `json:"title"`
}

var cfg = elasticsearch.Config{
Addresses: []string{
"http://localhost:9200",
},
}

func createClient() *elasticsearch.TypedClient {
client, err := elasticsearch.NewTypedClient(cfg)
if err != nil {
fmt.Printf("elasticsearch.NewTypedClient failed,err:", err)
return nil
}
return client
}

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)
}

func indexDocument(client *elasticsearch.TypedClient) {
d1 := Review{
ID: 1,
UserID: 78123,
Score: 4,
Content: "这是一个好评",
Tags: []Tag{
{
Code: 100,
Title: "好评",
}, {
Code: 1100,
Title: "物超所值",
}, {
Code: 9000,
Title: "有图",
},
},
Status: 2,
PublishTime: time.Now(),
}

resp, err := client.Index("my-review-1").
Id(cast.ToString(d1.ID)).Document(d1).
Do(context.Background())
if err != nil {
fmt.Printf("client.Index failed ,err:%v", err)
return
}
fmt.Printf("result:%#v\n", resp.Result)
}

func getDocument(client *elasticsearch.TypedClient, id string) {
resp, err := client.Get("my-review-id", id).Do(context.Background())
if err != nil {
fmt.Printf("get document by id failed,err:%v\n", err)
}
fmt.Printf("fileds:%s\n", resp.Fields)
}

func searchDocument(client *elasticsearch.TypedClient) {
client.Search().
Index("my-review-1").
Query(&types.Query{
MatchPhrase: map[string]types.MatchPhraseQuery{
"content": {Query: "好评"},
},
}).
Do(context.Background())
}

// 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"])
}

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)
}

// deleteDocument 删除文档
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)
}

// 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.Acknowledged)
}

[Getting started | Elasticsearch Go Client 8.12] | Elastic

[Examples | Elasticsearch Go Client 8.12] | Elastic


elasticSearch总结
http://example.com/2024/03/10/elasticSearch总结/
作者
Forrest
发布于
2024年3月10日
许可协议