简介

ES是一个开源的高扩展的分布式全文搜索引擎,它可以近乎实时的存储、检索数据。

环境配置

Elasticsearch 7.8.0 | Elastic

最新版本的需要Java11的环境,7.8版本的java1.8可用。

windows上点击bin/elasticsearch.bat启动,localhost:9200

倒排索引

keywordid
name1001,1002
zhang1001

使用内容搜索到id

索引的增删查

使用restfull风格的请求,发送PUT、DELETE、GET

URL:http://localhost:9200/shopping shopping是索引名称。

增加:PUT

删除:DELETE

查询:GET

查看全部索引信息:GET:http://localhost:9200/_cat/indices?v

文档的增删改

增加

POST:http://localhost:9200/shopping/_doc

request body中添加json字符串,如:

1
2
3
4
{
"name":"小猪",
"age":18
}

成功的响应:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
{
"_index": "shopping",
"_type": "_doc",
"_id": "HKPeWH8BmpBnrMt18vUi",
"_version": 1,
"result": "created",
"_shards": {
"total": 2,
"successful": 1,
"failed": 0
},
"_seq_no": 0,
"_primary_term": 1
}

从响应信息中看到,返回的ID为HKPeWH8BmpBnrMt18vUi,若想使用自定义的ID,则需要修改请求的URL,如:http://localhost:9200/shopping/_doc/1001 id为1001

查询

根据id查询

GET:http://localhost:9200/shopping/_doc/1001

1
2
3
4
5
6
7
8
9
10
11
12
13
{
"_index": "shopping",
"_type": "_doc",
"_id": "1001",
"_version": 2,
"_seq_no": 2,
"_primary_term": 1,
"found": true,
"_source": {
"name": "小猪",
"age": 18
}
}

查询索引下的所有文档信息

GET:http://localhost:9200/shopping/_search

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
{
"took": 56,
"timed_out": false,
"_shards": {
"total": 1,
"successful": 1,
"skipped": 0,
"failed": 0
},
"hits": {
"total": {
"value": 2,
"relation": "eq"
},
"max_score": 1.0,
"hits": [
{
"_index": "shopping",
"_type": "_doc",
"_id": "HKPeWH8BmpBnrMt18vUi",
"_score": 1.0,
"_source": {
"name": "小猪",
"age": 18
}
},
{
"_index": "shopping",
"_type": "_doc",
"_id": "1001",
"_score": 1.0,
"_source": {
"name": "小猪",
"age": 18
}
}
]
}
}

修改

覆盖性修改

PUT:http://localhost:9200/shopping/_doc/1001

request Body:

1
2
3
4
{
"name":"小狗",
"age":18
}

response:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
{
"_index": "shopping",
"_type": "_doc",
"_id": "1001",
"_version": 3,
"result": "updated",
"_shards": {
"total": 2,
"successful": 1,
"failed": 0
},
"_seq_no": 3,
"_primary_term": 1
}

局部数据修改

POST:http://localhost:9200/shopping/_update/1001

request body:

1
2
3
4
5
{
"doc":{
"age":20
}
}

response:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
{
"_index": "shopping",
"_type": "_doc",
"_id": "1001",
"_version": 5,
"result": "updated",
"_shards": {
"total": 2,
"successful": 1,
"failed": 0
},
"_seq_no": 5,
"_primary_term": 1
}

删除

DELETE:http://localhost:9200/shopping/_doc/1001

response:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
{
"_index": "shopping",
"_type": "_doc",
"_id": "1001",
"_version": 6,
"result": "deleted",
"_shards": {
"total": 2,
"successful": 1,
"failed": 0
},
"_seq_no": 6,
"_primary_term": 1
}

复杂查询

ES的搜索会对用户输入的内容进行分词操作,然后查询出与之相关的内容并按照相关度_score降序排列,比如:要查询的内容为{"name":"小猪"} ,则查询结果中包含所有name属性中包括的信息,例如:小猪小鸡大猪…..

条件查询

查询年龄为18的信息:

GET:http://localhost:9200/shopping/_search

request body:

1
2
3
4
5
6
7
{
"query":{
"match":{
"age":18
}
}
}

response:

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
{
"took": 2,
"timed_out": false,
"_shards": {
"total": 1,
"successful": 1,
"skipped": 0,
"failed": 0
},
"hits": {
"total": {
"value": 1,
"relation": "eq"
},
"max_score": 1.0,
"hits": [
{
"_index": "shopping",
"_type": "_doc",
"_id": "HKPeWH8BmpBnrMt18vUi",
"_score": 1.0,
"_source": {
"name": "小猪",
"age": 18
}
}
]
}
}

分页查询

GET :http://localhost:9200/shopping/_search

request body:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
{
"query":{
"match_all":{

}
},
"from":0,
"size":1,
"_source":["name"],
"sort":{
"age":{
"order":"desc"
}
}
}

参数:

from从那条开始查,第一个为0

size每页显示的数据的条数

_source指定要查询的属性,不加默认全部

sort对查询的内容进行排序后分页,此处的意思是根据age进行降序排序。降序:desc,升序:esc

response:

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
{
"took": 1,
"timed_out": false,
"_shards": {
"total": 1,
"successful": 1,
"skipped": 0,
"failed": 0
},
"hits": {
"total": {
"value": 4,
"relation": "eq"
},
"max_score": 1.0,
"hits": [
{
"_index": "shopping",
"_type": "_doc",
"_id": "HKPeWH8BmpBnrMt18vUi",
"_score": 1.0,
"_source": {
"name": "小猪",
"age": 18
}
}
]
}
}

多条件参数

与关系

request body:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
{
"query": {
"bool": {
"must": [
{
"match": {
"name": "小鸡"
}
},
{
"match": {
"age": 18
}
}
]
}
}
}

must为一个数组,代表必须满足的所有条件。

或关系

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
{
"query": {
"bool": {
"should": [
{
"match": {
"name": "小鸡"
}
},
{
"match": {
"age": 18
}
}
]
}
}
}

should为一个数组,进行查询时取或的关系。

范围限制

限制属性的取值范围,比如年龄>20

request body:

1
2
3
4
5
6
7
8
9
10
11
12
13
{
"query": {
"bool": {
"filter":{
"range":{
"age":{
"gt":20
}
}
}
}
}
}

response:

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
{
"took": 5,
"timed_out": false,
"_shards": {
"total": 1,
"successful": 1,
"skipped": 0,
"failed": 0
},
"hits": {
"total": {
"value": 2,
"relation": "eq"
},
"max_score": 0.0,
"hits": [
{
"_index": "shopping",
"_type": "_doc",
"_id": "IKMHWX8BmpBnrMt1ePVZ",
"_score": 0.0,
"_source": {
"name": "小鸡",
"age": 22
}
},
{
"_index": "shopping",
"_type": "_doc",
"_id": "IaMHWX8BmpBnrMt1qvUl",
"_score": 0.0,
"_source": {
"name": "阿姨",
"age": 60
}
}
]
}
}

完全匹配

由前文可知,ES会对内容进行分词操作,如何进行完全匹配呢?

request body:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
{
"query": {
"match_phrase":{
"name":"小猪"
}
},
"highlight":{
"fields":{
"name":{

}
}
}
}

只会查询到name为“小猪”的信息,highlight设置高亮显示:

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
{
"took": 53,
"timed_out": false,
"_shards": {
"total": 1,
"successful": 1,
"skipped": 0,
"failed": 0
},
"hits": {
"total": {
"value": 1,
"relation": "eq"
},
"max_score": 1.5606477,
"hits": [
{
"_index": "shopping",
"_type": "_doc",
"_id": "HKPeWH8BmpBnrMt18vUi",
"_score": 1.5606477,
"_source": {
"name": "小猪",
"age": 18
},
"highlight": {
"name": [
"<em>小</em><em>猪</em>"
]
}
}
]
}
}

聚合查询

分组

request body:

1
2
3
4
5
6
7
8
9
10
{
"aggs":{
"age-group":{ // 这个名字随便取
"terms":{
"field":"age"
}
}
},
"size":0 //不显示原始数据,下同
}

response

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
{
"took": 3,
"timed_out": false,
"_shards": {
"total": 1,
"successful": 1,
"skipped": 0,
"failed": 0
},
"hits": {
"total": {
"value": 4,
"relation": "eq"
},
"max_score": null,
"hits": []
},
"aggregations": {
"age-group": {
"doc_count_error_upper_bound": 0,
"sum_other_doc_count": 0,
"buckets": [
{
"key": 18,
"doc_count": 1
},
{
"key": 20,
"doc_count": 1
},
{
"key": 22,
"doc_count": 1
},
{
"key": 60,
"doc_count": 1
}
]
}
}
}

平均值

response body:

1
2
3
4
5
6
7
8
9
10
{
"aggs":{
"age-group":{
"avg":{
"field":"age"
}
}
},
"size":0
}

response:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
{
"took": 3,
"timed_out": false,
"_shards": {
"total": 1,
"successful": 1,
"skipped": 0,
"failed": 0
},
"hits": {
"total": {
"value": 4,
"relation": "eq"
},
"max_score": null,
"hits": []
},
"aggregations": {
"age-group": {
"value": 30.0
}
}
}

映射

创建映射

PUT:http://localhost:9200/user/_mapping

request body:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
{
"properties":{
"name":{
"type":"text", //文本类型,可被分词
"index":true // 可被索引
},
"sex":{
"type":"keyword", // 关键字类型,不可被分词
"index":true
},
"tel":{
"type":"keyword",
"index":false
}
}
}

name可以被分词查询,sex必须是完全匹配,不能通过tel进行查询。