示例数据
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# 创建mapping PUT /hotel { "mappings": { "properties": { "title": { "type": "text" }, "city": { "type": "keyword" }, "price": { "type": "double" }, "create_time": { "type": "date", "format": "yyyy-MM-dd HH:mm:ss" }, "amenities": { "type": "text" }, "full_room": { "type": "boolean" }, "location": { "type": "geo_point" }, "praise": { "type": "integer" } } } } # 导入数据 POST /_bulk {"index": {"_index": "hotel","_id":"001"}} {"title": "文雅酒店", "city": "青岛", "price": 556.00, "create_time": "2020-04-18 12:00:00", "amenities": "浴池,普通停车场/充电停车场", "full_room": false, "location": {"lat": 36.083078, "lon": 120.37566},"praise": 10} {"index": {"_index": "hotel","_id":"002"}} {"title": "金都嘉怡假日酒店", "city": "北京", "price": 337.00, "create_time": "2021-03-15 20:00:00", "amenities": "wifi,充电停车场/可升降停车场", "full_room": false, "location": {"lat": 39.915153, "lon": 116.4030},"praise": 60} {"index": {"_index": "hotel","_id":"003"}} {"title": "金都欣欣酒店", "city": "天津", "price": 200.00, "create_time": "2021-05-09 16:00:00", "amenities": "提供假日part,免费早餐,可充电停车场", "full_room": true, "location": {"lat": 39.186555, "lon": 117.162007},"praise": 30} {"index": {"_index": "hotel","_id":"004"}} {"title": "金都酒店", "city": "北京", "price": 500.00, "create_time": "2021-02-18 08:00:00", "amenities": "浴池(假日需预定),室内游泳池,普通停车场", "full_room": true, "location": {"lat": 39.915343, "lon": 116.4239},"praise": 20} {"index": {"_index": "hotel","_id":"005"}} {"title": "文雅精选酒店", "city": "北京", "price": 800.00, "create_time": "2021-01-01 08:00:00", "amenities": "浴池(假日需预定),wifi,普通停车场", "full_room": true, "location": {"lat": 39.918229, "lon": 116.422011},"praise": 20} {"index": {"_index": "hotel","_id":"006"}} {"title": "完美商务酒店", "city": "东莞", "price": 190.00, "create_time": "2022-04-15 17:24:00", "amenities": "无早餐,wifi,普通停车场", "full_room": false, "location": {"lat": 23.014747, "lon": 113.770511},"praise": 80}
搜索辅助功能
指定返回的字段
_source
子句可以设定返回结果的字段。
1
2
3
4
5
6
7# 示例 GET /${index_name}/_search { "_source": ["${field}","${field}"] # 仅返回指定字段 }
结果计数
_count
API可以对返回的数据进行数量统计。
1
2
3
4
5
6
7
8
9
10
11
12
13
14# 返回整个索引的文档数 GET /${index_name}/_count # 返回过滤后的文档数 GET /${index_name}/_count { "query": { "term": { "${field}": { "value": "${value}" } } } }
结果分页
在默认情况下,ES返回前10个搜索匹配的文档。可以通过设置from和size来定义搜索位置和每页显示的文档数量,from表示查询结果的起始下标,默认值为0,size表示从起始下标开始返回的文档个数,默认值为10。
分页的缺点:当用户查询第n页的时候,实际上es是把前n页的数据全部找出来,再去除前n-1页最后得到需要的数据返回,查最后一页就相当于全扫描。
1
2
3
4
5
6
7# 返回20个结果 GET /${index_name}/_search { "from": 0, "size": 20 }
在默认情况下,用户最多可以取得10000个文档,超过这个值会报错。可以修改max_result_window
的值来调整最大限制。
1
2
3
4
5
6
7
8
9PUT /${index_name}/_settings { "index": { "max_result_window": 20000 # 设置最大限制为20000 } }
滚动查询
scroll
适合那种需要一次性或分批拉出大量数据做离线处理、迁移等。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20# 语法 GET /${index_name}/_search?scroll=${time} # time指的是数据保留时间,最大不超过1d,也就是24h { "size": ${num} } # 示例 GET /hotel12/_search?scroll=1m # 查询10条数据,保留1分钟 { "size": 10 } # 上述命令会返回一个scroll_id,用scroll_id继续查询即可获取后续数据,无需指定索引,因为scroll_id是唯一的 # 重复请求以下api,最后会将全部数据取出 GET /_search/scroll { "scroll":"1m", "scroll_id":"DnF1ZXJ5VGhlbkZldGNoBAAAAAAABPP1FmRFSU9NM1VNU2JxNG9UUlNnSmpXMVEAAAAAAL7OTxYxT0dJOVJVMVFxU2I0N2xCR2IyVzJnAAAAAAC-j70WVVlOZkxQRzJRLXlMRlVMbEQtalBfUQAAAAAAyWm-Fk9HdGx1b3VsUXRLZHV4c1E1OExja0E=" }
性能分析
ES提供了profile功能,该功能详细地列出了搜索时每一个步骤的耗时,可以帮助用户对DSL的性能进行剖析。
1
2
3
4
5
6
7
8
9
10
11# 开启profile功能 GET /${index_name}/_search { "profile": true, "query": { "match": { "${field}": "${value}" } } }
评分分析
如果用户不指定按照某个字段进行升序或者降序排列,那么ES会使用打分算法计算的分数对文档进行排序。
ES提供了explain功能来帮助使用者查看搜索时的匹配详情。
1
2
3
4
5
6
7
8
9
10# explain使用示例 GET /${index_name}/_explain/${_id} { "query": { "match": { "${field}": "${value}" } } }
搜索匹配功能
查询所有文档
使用match_all
查询文档时,ES不对文档进行打分计算,默认情况下给每个文档赋予1.0的得分。用户可以通过boost参数设定该分值。
1
2
3
4
5
6
7
8
9
10
11# match_all默认也只会返回10条数据 GET /${index_name}/_search { "query": { "match_all": { "boost": ${num} # 设置文档的分值 } } }
关键字别查询
term查询
term
查询是结构化精准查询的主要查询方式,用于查询待查字段和查询值是否完全匹配。
1
2
3
4
5
6
7
8
9
10
11
12# 语法 GET /${index_name}/_search { "query": { "term": { "${field}": { "value": "${value}" } } } }
terms查询
terms
查询是term查询的扩展形式,用于查询一个或多个值与待查字段是否完全匹配。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16GET /${index_name}/_search { "query": { "terms": { "${field}": [ # 指定查询字段 "${value1}", # 指定查询值,多个值之间用逗号分隔 "${value2}", "${value3}", ... ] } } }
range查询
range
查询用于范围查询,一般是对数值型和日期型数据的查询。
范围比较符:
- gt:大于
- lt:小于
- gte:大于或等于
- lte:小于或等于
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24# 语法 GET /${index_name}/_search { "query": { "range": { "${field}": { "${范围比较符}": "${value}" } } } } # 示例:酒店价格在300-500之间 GET /hotel/_search { "query": { "range": { "price": { "gte": "300", "lte": "500" } } } }
注意,使用range查询时,查询值必须符合该字段在mappings中设置的规范。意思是不能拿字符串去搜数字类型的范围,会报错。
exists查询
使用exists
搜索可以找到某个字段不为空的文档。
字段不为空的条件有:
- 值存在且不是null
- 值不是空数组
- 值是数组,但不是[null]
字段为空的条件有:
- 值是
null
- 值是
[]
(空数组) - 值是
[null]
,元素为null的数组
1
2
3
4
5
6
7
8
9GET /${index_name}/_search { "query": { "exists": { "field": "${field}" } } }
布尔查询
must查询
当查询中包含must
查询时,表示当前查询为逻辑查询中的“与”查询,被命中的文档必须匹配该查询中的多个子查询结果。
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# 语法 GET /${index_name}/_search { "query": { "bool": { "must": [ # 可以包含多个[关键字级别查询](https://www.wolai.com/oY96bxtB5oQV9ZvaZfb9Eg#9v5dJHAJNQhHjef65M5wWa)和[布尔查询](https://www.wolai.com/oY96bxtB5oQV9ZvaZfb9Eg#pM18FZBFcZkW4wrb7ZVJJH) { # term查询 }, { # range查询或exists查询 } ] } } } # 示例:查询北京价格在350-500之间的酒店 GET /hotel/_search { "query": { "bool": { "must": [ { "term": { "city": { "value": "北京" } } }, { "range": { "price": { "gte": 350, "lte": 500 } } } ] } } }
should查询
当查询中包含should
查询时,表示当前查询为逻辑查询中的“或”查询。被命中的文档可以匹配该查询中的一个或多个子查询结果。
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# 语法 GET /${index_name}/_search { "query": { "bool": { "should": [ # 可以包含多个[term级别查询](https://www.wolai.com/oY96bxtB5oQV9ZvaZfb9Eg#9v5dJHAJNQhHjef65M5wWa)和布尔查询 { # term查询 }, { # range查询或exists查询 } ] } } } # 示例:查询北京或者天津的酒店 GET /hotel/_search { "query": { "bool": { "should": [ { "term": { "city": { "value": "北京" } } }, { "term": { "city": { "value": "天津" } } } ] } } }
must_not查询
当查询中包含must_not
查询时,表示当前查询为逻辑查询中的“非”查询,被命中的文档必须不匹配该查询中的多个子查询结果。
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# 语法 GET /${index_name}/_search { "query": { "bool": { "must_not": [ # 可以包含多个term级别查询和布尔查询 { # term查询 }, { # range查询或exists查询 } ] } } } # 示例:查询不是北京或者天津的酒店 GET /hotel/_search { "query": { "bool": { "must_not": [ { "term": { "city": { "value": "北京" } } }, { "term": { "city": { "value": "天津" } } } ] } } }
filter查询
filter查询即过滤查询,排除不匹配的文档。
区别:
- 其他布尔查询关注的是查询条件和文档的匹配程度,并按照匹配程度进行打分;
- 而filter查询关注的是查询条件和文档是否匹配,不打分,但是会对部分匹配结果进行缓存。
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# 语法 GET /${index_name}/_search { "query": { "bool": { "filter": [ # 可以包含多个term级别查询和布尔查询 { # term查询 }, { # range查询或exists查询 } ] } } } # 示例:查询北京不满房的酒店 GET /hotel/_search { "query": { "bool": { "filter": [ { "term": { "city": { "value": "北京" } } }, { "term": { "full_room": false } } ] } } }
Constant Score查询
Constant Score
查询可以过滤出某个文本字段是否包含某个词,但是会忽略TF(Term Frequency,检索词频率),也就是会忽略搜索关键字在文档中的次数。
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# 语法 GET /${index_name}/_search { "query": { "constant_score": { "filter": { # 可以加各种搜索方式,如term、match、bool等 } } } } # 示例:查询amenities字段包含关键词“停车场”的酒店 GET /hotel/_search { "_source": ["amenities"], "query": { "constant_score": { "filter": { "match": { "amenities": "停车场" } } } } } # 输出结果中,无论“停车场”出现几次,分数都是1,boost可以修改分数
Function Score查询
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
27
28
29
30
31
32
33
34
35
36
37
38# 语法 GET /${index_name}/_search { "query": { "function_score": { "query": {}, "functions": [ {} ] } } } # 示例 GET /hotel/_search { "_source": ["title","city"], "query": { "function_score": { "query": { # 查询语句为term查询 "term": { "city": { "value": "北京" } } }, "functions": [ # 使用随机分数函数 { "random_score": {} } ], "score_mode": "sum" # 最终分数设置为各个函数结果的总和 } } }
全文搜索
全文搜索首先对查询词进行分析,然后根据查询词的分词结果构建查询。
match查询
match
查询只要分词中的一个或者多个在文档中存在即可。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20# 语法 GET /${index_name}/_search { "query": { "match": { "${field}": "${value}" } } } # 示例:默认分词器会拆分成“金”“都”“酒”“店”,因此,只要文档中包含这4个字中的任何一个字,都会被搜索到 GET /hotel/_search { "_source": ["title"], "query": { "match": { "title": "金都酒店" } } }
multi_match查询
multi_match
查询可以在多个字段中查询关键词。
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# 语法 GET /${index_name}/_search { "query": { "multi_match": { "query": "${value}", "fields": [ "${field}", ... ] } } } # 示例 GET /hotel/_search { "_source": ["title","amenities"], "query": { "multi_match": { "query": "假日", "fields": [ "title", "amenities" ] } } }
match_phrase查询
match_phrase
用于搜索确切的短语或邻近的词语。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20# 语法 GET /${index_name}/_search { "query": { "match_phrase": { "${field}": "${value}" } } } # 示例 GET /hotel/_search { "query": { "match_phrase": { "title": "文雅酒店" } } } # 只会在示例数据中匹配”文雅酒店“,不会匹配”文雅精选酒店“
基于地理位置查询
对于geo_point
字段类型的查询方式有3种,分别为geo_distance
查询、geo_bounding_box
查询和geo_polygon
。
geo_distance查询
geo_distance
查询方式需要用户指定一个坐标点,在指定距离该点的范围后,ES即可查询到相应的文档。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16GET /hotel/_search { "_source": ["title","city","location"], "query": { "geo_distance": { "distance": "5km", # 指定范围为5km "location": { # 设置指定坐标点的纬度、精度 "lat": "39.915143", "lon": "116.4039" } } } }
搜索建议
搜索建议:即在用户输入搜索关键词的过程中系统进行自动补全。
当字段的类型定义为completion
时,才可以使用Completion Suggester
提供的搜索建议功能。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15GET /hotel_sug/_search { "suggest": { "hotel_zh_sug": { # 定义搜索建议的名称 "prefix": "如家", # 设置搜索建议的前缀 "completion": { # 设置搜索建议对应的字段 "field": "query_word" } } } }
排序功能
在默认情况下,ES对搜索结果是按照相关性降序排序的。
ES提供了sort
子句可以对数据进行排序。使用sort子句一般是按照字段信息进行排序,不受相关性影响,而且打分步骤需要耗费一定的硬件资源和时间,因此默认情况下,不对文档进行打分。
按普通字段值排序
sort默认是升序,即asc,可通过order字段设置为降序,即desc。
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# 语法 GET /${index_name}/_search { "sort": [ { "${field}": { "order": "desc" # 设置为降序排列 } } ] } # 示例 GET /hotel/_search { "_source": ["title","price"], "query": { "match": { "title": "金都" } }, "sort": [ # sort是个数组,可以按照多个字段进行排序 { "price": { "order": "desc" } } ] }
按地理距离排序
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
33GET /hotel/_search { "_source": ["title","city","location"], "query": { "geo_distance": { "distance": "5km", # 查询的地理范围 "location": { # 设置的中心点坐标 "lat": "39.915143", "lon": "116.4039" } } }, "sort": [ { "_geo_distance": { "location": { # 设置排序的中心点坐标 "lat": "39.915143", "lon": "116.4039" }, "order": "asc", # 距离由近到远 "unit": "km", # 排序所使用的距离单位 "distance_type": "plane" # 排序所使用的距离算法,默认算法是arc(精准但是耗时长),plane则相反 } } ] }
最后
以上就是感动大叔最近收集整理的关于Elasticsearch搜索操作的全部内容,更多相关Elasticsearch搜索操作内容请搜索靠谱客的其他文章。
发表评论 取消回复