ElasticSearch的各种查询
六、 ElasticSearch的各种查询
6.1 term&terms查询【重点】
6.1.1 term查询
term的查询是代表完全匹配,搜索之前不会对你搜索的关键字进行分词,对你的关键字去文档分词库中去匹配内容。
# term查询
POST /sms-logs-index/sms-logs-type/_search
{
"from": 0, # limit ?
"size": 5, # limit x,?
"query": {
"term": {
"province": {
"value": "北京"
}
}
}
}
代码实现方式
// Java代码实现方式
6.1.2 terms查询
terms和term的查询机制是一样,都不会将指定的查询关键字进行分词,直接去分词库中匹配,找到相应文档内容。
terms是在针对一个字段包含多个值的时候使用。
term:where province = 北京;
terms:where province = 北京 or province = ?or province = ?
# terms查询
POST /sms-logs-index/sms-logs-type/_search
{
"query": {
"terms": {
"province": [
"北京",
"山西",
"武汉"
]
}
}
}
代码实现方式
// Java实现
6.2 match查询【重点】
match查询属于高层查询,他会根据你查询的字段类型不一样,采用不同的查询方式。
查询的是日期或者是数值的话,他会将你基于的字符串查询内容转换为日期或者数值对待。
如果查询的内容是一个不能被分词的内容(keyword),match查询不会对你指定的查询关键字进行分词。
如果查询的内容时一个可以被分词的内容(text),match会将你指定的查询内容根据一定的方式去分词,去分词库中匹配指定的内容。
match查询,实际底层就是多个term查询,将多个term查询的结果给你封装到了一起。
6.2.1 match_all查询
查询全部内容,不指定任何查询条件。
# match_all查询
POST /sms-logs-index/sms-logs-type/_search
{
"query": {
"match_all": {}
}
}
代码实现方式
// java代码实现
6.2.2 match查询
指定一个Field作为筛选的条件
# match查询
POST /sms-logs-index/sms-logs-type/_search
{
"query": {
"match": {
"smsContent": "收货安装"
}
}
}
代码实现方式
6.2.3 布尔match查询
基于一个Field匹配的内容,采用and或者or的方式连接,注意:此时field必须是text类型
# 布尔match查询
POST /sms-logs-index/sms-logs-type/_search
{
"query": {
"match": {
"smsContent": {
"query": "中国 健康",
"operator": "and" # 内容既包含中国也包含健康
}
}
}
}
# 布尔match查询
POST /sms-logs-index/sms-logs-type/_search
{
"query": {
"match": {
"smsContent": {
"query": "中国 健康",
"operator": "or" # 内容包括健康或者包括中国
}
}
}
}
代码实现方式
// Java代码实现
6.2.4 multi_match查询
match针对一个field做检索,multi_match针对多个field进行检索,多个field对应一个text。
# multi_match 查询
POST /sms-logs-index/sms-logs-type/_search
{
"query": {
"multi_match": {
"query": "北京", # 指定text
"fields": ["province","smsContent"] # 指定field们
}
}
}
代码实现方式
// java代码实现
6.3 其他查询
6.3.1 id查询
根据id查询 where id = ?
# id查询
GET /sms-logs-index/sms-logs-type/1
代码实现方式
// Java代码实现
6.3.2 ids查询
根据多个id查询,类似MySQL中的where id in(id1,id2,id2...)
# ids查询
POST /sms-logs-index/sms-logs-type/_search
{
"query": {
"ids": {
"values": ["1","2","3"]
}
}
}
代码实现方式
// Java代码实现
6.3.3 prefix查询
前缀查询,可以通过一个关键字去指定一个Field的前缀,从而查询到指定的文档。
#prefix 查询
POST /sms-logs-index/sms-logs-type/_search
{
"query": {
"prefix": {
"corpName": {
"value": "途虎"
}
}
}
}
代码实现方式
// Java实现前缀查询
6.3.4 fuzzy查询
模糊查询,我们输入字符的大概,ES就可以去根据输入的内容大概去匹配一下结果。
# fuzzy查询
POST /sms-logs-index/sms-logs-type/_search
{
"query": {
"fuzzy": {
"corpName": {
"value": "盒马先生",
"prefix_length": 2 # 指定前面几个字符是不允许出现错误的
}
}
}
}
代码实现方式
// Java代码实现Fuzzy查询
6.3.5 wildcard查询
通配查询,和MySQL中的like是一个套路,可以在查询时,在字符串中指定通配符*和占位符?
# wildcard 查询
POST /sms-logs-index/sms-logs-type/_search
{
"query": {
"wildcard": {
"corpName": {
"value": "中国*" # 可以使用*和?指定通配符和占位符
}
}
}
}
代码实现方式
// Java代码实现Wildcard查询
6.3.6 range查询
范围查询,只针对数值类型,对某一个Field进行大于或者小于的范围指定
# range 查询
POST /sms-logs-index/sms-logs-type/_search
{
"query": {
"range": {
"fee": {
"gt": 5,
"lte": 10
# 可以使用 gt:> gte:>= lt:< lte:<=
}
}
}
}
代码实现方式
// Java实现range范围查询
6.3.7 regexp查询
正则查询,通过你编写的正则表达式去匹配内容。
# regexp 查询
POST /sms-logs-index/sms-logs-type/_search
{
"query": {
"regexp": {
"mobile": "180[0-9]{8}" # 编写正则
}
}
}
代码实现方式
// Java代码实现正则查询
6.4 深分页Scroll
ES对from + size是有限制的,from和size二者之和不能超过1W
原理:
from+size在ES查询数据的方式:
第一步现将用户指定的关键进行分词。
第二步将词汇去分词库中进行检索,得到多个文档的id。
第三步去各个分片中去拉取指定的数据。耗时较长。
第四步将数据根据score进行排序。耗时较长。
第五步根据from的值,将查询到的数据舍弃一部分。
第六步返回结果。
scroll+size在ES查询数据的方式:
第一步现将用户指定的关键进行分词。
第二步将词汇去分词库中进行检索,得到多个文档的id。
第三步将文档的id存放在一个ES的上下文中。
第四步根据你指定的size的个数去ES中检索指定个数的数据,拿完数据的文档id,会从上下文中移除。
第五步如果需要下一页数据,直接去ES的上下文中,找后续内容。
第六步循环第四步和第五步
# 执行scroll查询,返回第一页数据,并且将文档id信息存放在ES上下文中,指定生存时间1m
POST /sms-logs-index/sms-logs-type/_search?scroll=1m
{
"query": {
"match_all": {}
},
"size": 2,
"sort": [ # 排序
{
"fee": {
"order": "desc"
}
}
]
}
# 根据scroll查询下一页数据
POST /_search/scroll
{
"scroll_id": "<根据第一步得到的scorll_id去指定>",
"scroll": "<scorll信息的生存时间>"
}
# 删除scroll在ES上下文中的数据
DELETE /_search/scroll/scroll_id
代码实现方式
// Java实现scroll分页
6.5 delete-by-query
根据term,match等查询方式去删除大量的文档
# delete-by-query
POST /sms-logs-index/sms-logs-type/_delete_by_query
{
"query": {
"range": {
"fee": {
"lt": 4
}
}
}
}
代码实现方式
// Java代码实现
6.6 复合查询
6.6.1 bool查询
复合过滤器,将你的多个查询条件,以一定的逻辑组合在一起。
must: 所有的条件,用must组合在一起,表示And的意思
must_not:将must_not中的条件,全部都不能匹配,标识Not的意思
should:所有的条件,用should组合在一起,表示Or的意思
# 查询省份为武汉或者北京
# 运营商不是联通
# smsContent中包含中国和平安
# bool查询
POST /sms-logs-index/sms-logs-type/_search
{
"query": {
"bool": {
"should": [
{
"term": {
"province": {
"value": "北京"
}
}
},
{
"term": {
"province": {
"value": "武汉"
}
}
}
],
"must_not": [
{
"term": {
"operatorId": {
"value": "2"
}
}
}
],
"must": [
{
"match": {
"smsContent": "中国"
}
},
{
"match": {
"smsContent": "平安"
}
}
]
}
}
}
代码实现方式
// Java代码实现Bool查询
6.6.2 boosting查询
boosting查询可以帮助我们去影响查询后的score。
positive:只有匹配上positive的查询的内容,才会被放到返回的结果集中。
negative:如果匹配上和positive并且也匹配上了negative,就可以降低这样的文档score。
negative_boost:指定系数,必须小于1.0
关于查询时,分数是如何计算的:
搜索的关键字在文档中出现的频次越高,分数就越高
指定的文档内容越短,分数就越高
我们在搜索时,指定的关键字也会被分词,这个被分词的内容,被分词库匹配的个数越多,分数越高
# boosting查询 收货安装
POST /sms-logs-index/sms-logs-type/_search
{
"query": {
"boosting": {
"positive": {
"match": {
"smsContent": "收货安装"
}
},
"negative": {
"match": {
"smsContent": "王五"
}
},
"negative_boost": 0.5
}
}
}
代码实现方式
// Java实现Boosting查询
6.7 filter查询
query,根据你的查询条件,去计算文档的匹配度得到一个分数,并且根据分数进行排序,不会做缓存的。
filter,根据你的查询条件去查询文档,不去计算分数,而且filter会对经常被过滤的数据进行缓存。
# filter查询
POST /sms-logs-index/sms-logs-type/_search
{
"query": {
"bool": {
"filter": [
{
"term": {
"corpName": "盒马鲜生"
}
},
{
"range": {
"fee": {
"lte": 4
}
}
}
]
}
}
}
代码实现方式
// Java实现filter操作
6.8 高亮查询【重点】
高亮查询就是你用户输入的关键字,以一定的特殊样式展示给用户,让用户知道为什么这个结果被检索出来。
高亮展示的数据,本身就是文档中的一个Field,单独将Field以highlight的形式返回给你。
ES提供了一个highlight属性,和query同级别的。
fragment_size:指定高亮数据展示多少个字符回来。
pre_tags:指定前缀标签,举个栗子< font color="red" > < font color="red" > 盒马< /font >
post_tags:指定后缀标签,举个栗子< /font >
fields:指定哪几个Field以高亮形式返回

RESTful实现
# highlight查询
POST /sms-logs-index/sms-logs-type/_search
{
"query": {
"match": {
"smsContent": "盒马"
}
},
"highlight": {
"fields": {
"smsContent": {}
},
"pre_tags": "<font color='red'>",
"post_tags": "</font>",
"fragment_size": 10
}
}
代码实现方式
// Java实现高亮查询
6.9 聚合查询【重点】
ES的聚合查询和MySQL的聚合查询类似,ES的聚合查询相比MySQL要强大的多,ES提供的统计数据的方式多种多样。
# ES聚合查询的RESTful语法
POST /index/type/_search
{
"aggs": {
"名字(agg)": {
"agg_type": {
"属性": "值"
}
}
}
}
6.9.1 去重计数查询
去重计数,即Cardinality,第一步先将返回的文档中的一个指定的field进行去重,统计一共有多少条
# 去重计数查询 北京 上海 武汉 山西
POST /sms-logs-index/sms-logs-type/_search
{
"aggs": {
"agg": {
"cardinality": {
"field": "province"
}
}
}
}
代码实现方式
// Java代码实现去重计数查询
6.9.2 范围统计
统计一定范围内出现的文档个数,比如,针对某一个Field的值在 0~100,100~200,200~300之间文档出现的个数分别是多少。
范围统计可以针对普通的数值,针对时间类型,针对ip类型都可以做相应的统计。
range,date_range,ip_range
数值统计
# 数值方式范围统计
POST /sms-logs-index/sms-logs-type/_search
{
"aggs": {
"agg": {
"range": {
"field": "fee",
"ranges": [
{
"to": 5
},
{
"from": 5, # from有包含当前值的意思
"to": 10
},
{
"from": 10
}
]
}
}
}
}
时间范围统计
# 时间方式范围统计
POST /sms-logs-index/sms-logs-type/_search
{
"aggs": {
"agg": {
"date_range": {
"field": "createDate",
"format": "yyyy",
"ranges": [
{
"to": 2000
},
{
"from": 2000
}
]
}
}
}
}
ip统计方式
# ip方式 范围统计
POST /sms-logs-index/sms-logs-type/_search
{
"aggs": {
"agg": {
"ip_range": {
"field": "ipAddr",
"ranges": [
{
"to": "10.126.2.9"
},
{
"from": "10.126.2.9"
}
]
}
}
}
}
代码实现方式
// Java实现数值 范围统计
6.9.3 统计聚合查询
他可以帮你查询指定Field的最大值,最小值,平均值,平方和等
使用:extended_stats
# 统计聚合查询
POST /sms-logs-index/sms-logs-type/_search
{
"aggs": {
"agg": {
"extended_stats": {
"field": "fee"
}
}
}
}
代码实现方式
// Java实现统计聚合查询
其他的聚合查询方式查看官方文档:https://www.elastic.co/guide/en/elasticsearch/reference/6.5/index.html
6.10 地图经纬度搜索
ES中提供了一个数据类型 geo_point,这个类型就是用来存储经纬度的。
创建一个带geo_point类型的索引,并添加测试数据
# 创建一个索引,指定一个name,locaiton
PUT /map
{
"settings": {
"number_of_shards": 5,
"number_of_replicas": 1
},
"mappings": {
"map": {
"properties": {
"name": {
"type": "text"
},
"location": {
"type": "geo_point"
}
}
}
}
}
# 添加测试数据
PUT /map/map/1
{
"name": "天安门",
"location": {
"lon": 116.403981,
"lat": 39.914492
}
}
PUT /map/map/2
{
"name": "海淀公园",
"location": {
"lon": 116.302509,
"lat": 39.991152
}
}
PUT /map/map/3
{
"name": "北京动物园",
"location": {
"lon": 116.343184,
"lat": 39.947468
}
}
6.10.1 ES的地图检索方式
| 语法 | 说明 |
|---|---|
| geo_distance | 直线距离检索方式 |
| geo_bounding_box | 以两个点确定一个矩形,获取在矩形内的全部数据 |
| geo_polygon | 以多个点,确定一个多边形,获取多边形内的全部数据 |
6.10.2 基于RESTful实现地图检索
geo_distance
# geo_distance
POST /map/map/_search
{
"query": {
"geo_distance": {
"location": { # 确定一个点
"lon": 116.433733,
"lat": 39.908404
},
"distance": 3000, # 确定半径
"distance_type": "arc" # 指定形状为圆形
}
}
}
geo_bounding_box
# geo_bounding_box
POST /map/map/_search
{
"query": {
"geo_bounding_box": {
"location": {
"top_left": { # 左上角的坐标点
"lon": 116.326943,
"lat": 39.95499
},
"bottom_right": { # 右下角的坐标点
"lon": 116.433446,
"lat": 39.908737
}
}
}
}
}
geo_polygon
# geo_polygon
POST /map/map/_search
{
"query": {
"geo_polygon": {
"location": {
"points": [ # 指定多个点确定一个多边形
{
"lon": 116.298916,
"lat": 39.99878
},
{
"lon": 116.29561,
"lat": 39.972576
},
{
"lon": 116.327661,
"lat": 39.984739
}
]
}
}
}
}
6.10.3 Java实现geo_polygon
// 基于Java实现geo_polygon查询
本文来自博客园,作者:forever226,转载请注明原文链接:https://www.cnblogs.com/forever226/p/16504102.html



浙公网安备 33010602011771号