ElasticSearch高级操作

数据准备

  • 将ES中的索引全部删除
  • 添加索引: PUT hotel
  • 添加几个文档
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
PUT /hotel
{
"mappings": {
"properties": {
"id":{
"type": "keyword"
},
"name":{
"type": "keyword",
"analyzer": "ik_max_word",
"copy_to": "all"
},
"address":{
"type": "keyword",
"index": false
},
"price":{
"type": "integer"
},
"score":{
"type": "integer"
},
"brand":{
"type": "keyword",
"copy_to": "all"
},
"city":{
"type": "keyword"
},
"starName":{
"type": "keyword"
},
"business":{
"type": "keyword",
"copy_to": "all"
},
"location":{
"type": "geo_point"
},
"pic":{
"type": "keyword",
"index": false
},
"all":{
"type": "keyword",
"analyzer": "ik_max_word"
}
}
}
}


GET /hotel/_search

可以注意到Hotel映射结构中:namebrandbusiness三个字段分别使用了copy_to属性,它允许你将一个或多个字段的原始值复制到另一个指定的字段,优势在于:合并内容、简化查询、分析一致性

Hotel查询结果

高级查询

全文检索查询

  • 请求方式:GET 索引名/_search
  • 请求体内容
1
2
3
4
5
6
7
8
9
10
# 全文检索查询
# match对用户输入的内容进行分词然后去倒排索引库检索
GET /hotel/_search
{
"query": {
"match": {
"name": "如家"
}
}
}

image-20240201110008926

使用合并内容字段all进行查询,查询外滩如家将分词为 外滩、如家,即包含两个其中一个都命中结果

image-20240201111306170

查询所有文档

  • 请求方式:GET 索引名/_search
  • 请求体内容
1
2
3
4
5
6
GET /hotel/_search
{
"query": {
"match_all": {}
}
}

image-20240201111516906

字段匹配查询:multi_match

查询的字段越多效率越慢

  • multi_matchmatch 类似,不同的是它可以在多个字段中查询。
  • 请求方式:GET 索引名/_search
  • 请求体内容
1
2
3
4
5
6
7
8
9
10
# multi_match 多个字段搜索,参与查询字段越多,查询性能越差copy_to 
GET /hotel/_search
{
"query": {
"multi_match": {
"query": "外滩如家",
"fields": ["brand","name","business"]
}
}
}

image-20240201111616840

单关键字精确查询:term

  • term 查询,精确的关键词匹配查询,不对查询条件进行分词,即只能单关键字精确查询。
  • 请求方式:GET 索引名/_search
  • 请求体内容
1
2
3
4
5
6
7
8
9
10
11
12
#精确查询 一般查找KeyWord、数值、日期、Boolean
# term
GET /hotel/_search
{
"query": {
"term": {
"city": {
"value": "深圳"
}
}
}
}

image-20240201111721811

多关键字精确查询:terms

  • terms 查询和 term 查询一样,但它允许你指定多值进行匹配。如果这个字段包含了指定值中的任何一个值,那么这个文档满足条件,类似于 mysql 的 in
  • 请求方式:GET 索引名/_search
  • 请求体内容
1
2
3
4
5
6
7
8
9
10
11
12
GET /hotel/_search
{
"query": {
"terms": {
"name": [
"上海",
"深圳"
]
}
}
}

image-20240201111859144

指定字段查询:_source

  • 默认情况下,Elasticsearch 在搜索的结果中,会把文档中保存在 _source 的所有字段都返回。
  • 如果我们只想获取其中的部分字段,我们可以添加 _source 的过滤
  • 请求方式:GET 索引名/_search
  • 请求体内容
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
GET /hotel/_search
{
"_source": [
"name",
"price",
"address"
],
"query": {
"terms": {
"name": [
"上海",
"深圳"
]
}
}
}

image-20240201112213271

过滤字段:includes&excludes

  • includes:来指定想要显示的字段
  • excludes:来指定不想要显示的字段
  • 请求方式:GET 索引名/_search
  • 请求体内容
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
GET /hotel/_search
{
"_source": {
"includes": [
"name",
"price"
]
},
"query": {
"terms": {
"name": [
"上海"
]
}
}
}

查询名称包含上海的酒店,返回name、price信息

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
GET /hotel/_search
{
"_source": {
"excludes": [
"name",
"price"
]
},
"query": {
"terms": {
"name": [
"上海"
]
}
}
}

查询名称为上海的酒店信息,排除name和价格

组合查询:bool

  • bool 把各种其它查询通过 must(必须,类似 and)、must_not(必须不,类似 not)、should(应该 类似 or)的方式进行组合
  • 请求方式:GET 索引名/_search
  • 请求体内容

查询名称必须包含如家,价格不能超过400,并且在我位置10km范围内的酒店,且结果按价格高到低排序

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
GET /hotel/_search
{
"query": {
"bool": {
"must": [
{
"match": {
"name": "如家"
}
}
],
"must_not": [
{
"range": {
"price": {
"gt": 400
}
}
}
],
"filter": [
{
"geo_distance": {
"distance": "10km",
"location": {
"lat": 31.21,
"lon": 121.5
}
}
}
]
}
},
"sort": [
{
"price": "asc"
}
]
}

image-20240201113356960

范围查询:range

  • range 查询找出那些落在指定区间内的数字或者时间。range 查询允许以下字符
操作符说明
gt>
gte>=
lt<
lte<=

查询价格1000-3000的酒店信息

1
2
3
4
5
6
7
8
9
10
11
12
# range 范围查询
GET /hotel/_search
{
"query": {
"range": {
"price": {
"gte": 1000,
"lte": 3000
}
}
}
}

image-20240201113524705

模糊查询:fuzzy

fuzzy:返回包含与搜索字词相似的字词的文档,更多fuzzy有关解释请查看官方文档 (opens new window) -编辑距离是将一个术语转换为另一个术语所需的一个字符更改的次数。这些更改可以包括:

更改字符(box → fox)

删除字符(black → lack)

插入字符(sic → sick)

转置两个相邻字符(act → cat)

为了找到相似的术语,fuzzy 查询会在指定的编辑距离内创建一组搜索词的所有可能的变体或扩展。然后查询返回每个扩展的完全匹配。

通过 fuzziness 修改编辑距离。一般使用默认值 AUTO,根据术语的长度生成编辑距离。

请求方式:GET 索引名/_search

1
2
3
4
5
6
7
8
9
10
11

GET /hotel/_search
{
"query": {
"fuzzy": {
"all": {
"value": "乡"
}
}
}
}

image-20240201113725623

精确查询地理位置:geo_distance

1
2
3
4
5
6
7
8
9
10
11

# 精确查询地理位置
GET /hotel/_search
{
"query": {
"geo_distance":{
"distance":"2km",
"location":"31.21,121.5"
}
}
}

image-20240201113923477

复合查询:function_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

# 复合查询
# function score 查询
GET /hotel/_search
{
"query": {
"function_score": {
"query": {
"match": {
"all": "外滩"
}
},
"functions": [
{
"filter": {
"term": {
"brand": "如家"
}
},
"weight": 10
}
],
"boost_mode": "sum"
}
}
}

image-20240201114113309

前缀查询:prefix

  • 请求方式:GET 索引名/_search
  • 请求体内容
1
2
3
4
5
6
7
8
9
10
GET /hotel/_search
{
"query": {
"prefix": {
"name": {
"value": "上"
}
}
}
}

image-20240201114255956