数据准备
# 创建索引,设置分片副本,配置映射
PUT /demo
{
"settings":{
"number_of_replicas": 1,
"number_of_shards": 3
},
"mappings":{
"user":{
"properties":{
"name":{"type":"text"},
"age":{"type":"integer"},
"sex":{"type":"text"},
"remark":{"type":"text"},
"create_time":{"type":"date","format":"yyyy-MM-dd||yyyy/MM/dd||yyyy-MM-dd HH:mm:ss||epoch_millis"}
}
}
}
}
# 查看 mapping
GET /demo/user/_mapping
# 批量新增数据
POST /demo/user/_bulk
{"index":{"_index":"demo","_type":"user","_id":1}}
{"name":"kevin","age":24,"sex":"男","remark":"我是kevin","create_time":"2020-05-04"}
{"index":{"_index":"demo","_type":"user","_id":2}}
{"name":"cao","age":23,"sex":"男","remark":"我是cao","create_time":"2020-05-03"}
{"index":{"_index":"demo","_type":"user","_id":3}}
{"name":"mr.cao","age":22,"sex":"男","remark":"我是mr.cao","create_time":"2020-05-02"}
{"index":{"_index":"demo","_type":"user","_id":4}}
{"name":"kevin","age":21,"sex":"男","remark":"我是kevin","create_time":"2020-05-02"}
{"index":{"_index":"demo","_type":"user","_id":5}}
{"name":"coco","age":21,"sex":"女","remark":"我是coco","create_time":"2020-05-04"}
{"index":{"_index":"demo","_type":"user","_id":6}}
{"name":"co","age":20,"sex":"女","remark":"我是co","create_time":"2020-05-03"}
{"index":{"_index":"demo","_type":"user","_id":7}}
{"name":"coco","age":19,"sex":"女","remark":"我是coco","create_time":"2020-05-02"}
# 查询测试
# 查询name为kevin
GET /demo/user/_search?q=name:kevin
# 查询name为kevin且以age倒序
GET /demo/user/_search?q=name:kevin&sort=age:desc
# 查询前先校验语句是否正确
GET /demo/user/_validate/query?explain
{
"query":{
"match":{
"name":"kevin"
}
}
}
模糊查询时使用match,精准查询时使用term。
term query:直接对关键词准确查找,该查询只适合keyword、numeric、date。
term:查询某个字段中含有某个关键词的文档。
terms:查询某个字段中含有多个关键词的文档。
match query:对所查找的关键词进行分词,在根据分词匹配查找。
match_all:查询所有文档。
multi_match:指定多个字段。
match_phrase:短语匹配查询。
ES检索引擎会先分析查询字符串,从分析后的文本中构建短语查询,表示必须匹配短语中所有的分词,并保证各个分词的相对位置不变。
from:从第几条数据开始查询。
size:需要查询的个数。
sort:实现排序,desc降序,asc升序。
range:实现范围查询。(参数:from,to,include_lower,include_upper,boost)
include_lower:是否包含范围的左边界,默认true。
include_upper:是否包含范围的右边界,默认true。
wildcard:允许使用通配符*和?进行查询
*:表示0或者多个字符
?:表示任意一个字符
fuzzy:实现模糊查询
value:查询的关键字
boost:查询的权值,默认值1.0
min_similarity:设置匹配的最小相似度,默认值0.5,对于字符串,取值0-1(包括0和1),对于数值,取值可能大于1,对于日期,取值为1d,1m等,1d为1天。
prefix_length:指明区分词项的共同前缀长度,默认0.
max_expansions:查询中的词项可以扩展的数目,默认可以无限大。
filter是不计算相关性的,同时可以cache,所以filter效率高于query。
范围过滤:
gte:>=(大于等于)
gt:>(大于)
lte:<=(小于等于)
lt:<(小于)
bool过滤
must:必须满足的条件(and)
should:可以满足也可以不满足的条件(or)
must_not:不需要满足的条件(not)
term query:直接对关键词准确查找,该查询只适合keyword、numeric、date。
term:查询某个字段中含有某个关键词的文档。
terms:查询某个字段中含有多个关键词的文档。
term查询
# term指定查询name为kevin的数据
GET /demo/user/_search
{
"query":{
"term":{"name":"kevin"}
}
}
terms查询
# terms指定查询name为kevin与cao的数据
GET /demo/user/_search
{
"query":{
"terms":{
"name":["kevin","cao"]
}
}
}
from:从第几条数据开始查询,size:需要查询几条数据
# 分页查询
GET /demo/user/_search
{
"query":{
"terms":{
"name":["kevin","coco"]
}
},
"from":0,
"size":3
}
# 查询时返回版本号,默认version为false
GET /demo/user/_search
{
"version":"true",
"query": {
"terms": {
"name": ["kevin"]
}
}
}
match query:对所查找的关键词进行分词,在根据分词匹配查找。
match_all:查询所有文档。
multi_match:指定多个字段。
match_phrase:短语匹配查询。
match_all:查询所有文档。
# 查询所有用户
GET /demo/user/_search
{
"query":{
"match_all":{}
}
}
# 指定查询,name为kevin且以age倒序
GET /demo/user/_search
{
"query":{
"match":{
"name":"kevin"
}
},
"sort":[
{
"age":"desc"
}
]
}
multi_match:指定多个字段。
# 在多个字段中查询包含谁,kevin,coco的数据
GET /demo/user/_search
{
"query":{
"multi_match":{
"query":"谁 kevin coco",
"fields":["name","remark"]
}
}
}
# "query":"谁 kevin coco",查询的语句,fields查询的字段
match_phrase:短语完全匹配查询。
ES检索引擎会先分析查询字符串,从分析后的文本中构建短语查询,表示必须匹配短语中所有的分词,并保证各个分词的相对位置不变。
# 精准匹配所有包含(完全匹配),必须包含
GET /demo/user/_search
{
"query":{
"match_phrase":{
"remark":{
"query":"我",
"slop":1
}
}
}
}
# "slop"是可调节因子,"slop":1则表示往后移一个单词也能匹配
match_phrase_prefix:前缀匹配查询
# 匹配name的开头是co
GET /demo/user/_search
{
"query":{
"match_phrase_prefix":{
"name":{
"query":"co"
}
}
}
}
from:从第几条数据开始查询,size:需要查询几条数据
# 分页查询
GET /demo/user/_search
{
"query":{
"match":{
"name":"kevin"
}
},
"from":0,
"size":2
}
# 查询name为kevin的name,age,create_time字段
GET /demo/user/_search
{
"query":{
"match":{
"name":"kevin"
}
},
"_source":[
"name",
"age",
"create_time"
]
}
includes:包含的字段展示
excludes:不包含的字段展示
# 包含的字段展示
GET /demo/user/_search
{
"query":{
"match_all":{}
},
"_source":{
"includes":["name","sex"]
}
}
# 不包含的字段展示
GET /demo/user/_search
{
"query":{
"match_all":{}
},
"_source":{
"excludes":["age","create_time"]
}
}
# 展示字段名包含m的字段
GET /demo/user/_search
{
"_source":{
"includes":"*m*"
},
"query":{
"match_all":{}
}
}
# 展示字段名包含m的字段,并不展示name与最后为e的字段
GET /demo/user/_search
{
"_source":{
"includes":"*m*",
"excludes":["name","*e"]
},
"query":{
"match_all":{}
}
}
sort:实现排序,desc降序,asc升序。
# 根据age做升序排序
GET /demo/user/_search
{
"query":{
"match_all":{}
},
"sort":{
"age":{
"order":"asc"
}
}
}
range:实现范围查询。(参数:from,to,include_lower,include_upper,boost)
include_lower:是否包含范围的左边界,默认true。
include_upper:是否包含范围的右边界,默认true。
# 查询create_time为2020-05-01到05的数据
GET /demo/user/_search
{
"query":{
"range":{
"create_time":{
"from":"2020-05-01",
"to":"2020-05-05"
}
}
}
}
# 查询age为19到21的数据,不包含21
GET /demo/user/_search
{
"query":{
"range":{
"age":{
"from":19,
"to":21,
"include_lower":true,
"include_upper":false
}
}
}
}
wildcard:允许使用通配符*和?进行查询
*:表示0或者多个字符
?:表示任意一个字符
# 模糊匹配name中最右面为co的数据
GET /demo/user/_search
{
"query":{
"wildcard":{
"name":"*co"
}
}
}
# 模糊匹配name中c与o之间还有一个值的数据
GET /demo/user/_search
{
"query":{
"wildcard":{
"name":"c?o"
}
}
}
fuzzy:实现模糊查询
value:查询的关键字
boost:查询的权值,默认值1.0
min_similarity:设置匹配的最小相似度,默认值0.5,对于字符串,取值0-1(包括0和1),对于数值,取值可能大于1,对于日期,取值为1d,1m等,1d为1天。
prefix_length:指明区分词项的共同前缀长度,默认0.
max_expansions:查询中的词项可以扩展的数目,默认可以无限大。
# 模糊匹配分词后remark有kevin的数据
GET /demo/user/_search
{
"query":{
"fuzzy":{
"remark":{
"value":"kevin"
}
}
}
}
# 比如remark的数据为我是keivn,会分词为dos[0]:我[0] 是[1] kevin[2]
# 高亮显示搜索结果
GET /demo/user/_search
{
"query":{
"match":{
"name":"coco"
}
},
"highlight":{
"fields": {
"name":{}
}
}
}
filter是不计算相关性的,同时可以cache,所以filter效率高于query。
搜索结果:
性能:
当query与filter同时使用时filter会先执行,并且同时兼顾两者的特性
# 过滤只取指定的结果
GET /demo/user/_search
{
"post_filter":{
"term":{
"age":21
}
}
}
# 过滤只取指定的多个结果
GET /demo/user/_search
{
"post_filter":{
"terms":{
"age":[21,23]
}
}
}
新增一个用户id字段设置映射不分词
PUT /demo/_mapping/user
{
"properties":{
"user_id":{
"type":"text",
"index":"false"
}
}
}
bool过滤
must:必须满足的条件(and)
should:可以满足也可以不满足的条件(or)
must_not:不需要满足的条件(not)
格式
{
"bool":{
"must":[],
"should":[],
"must_not":[]
}
}
普通bool案例
#获取name=keivn or age = 20 且 age <> 24
GET /demo/user/_search
{
"post_filter":{
"bool":{
"should":[
{"term":{"name":"kevin"}},
{"term":{"age":20}}
],
"must_not":{
"term":{"age":24}
}
}
}
}
嵌套bool
# 嵌套bool,name=kevin or (name=coco and age=21)
GET /demo/user/_search
{
"post_filter":{
"bool":{
"should":[
{"term":{"name":"kevin"}},
{
"bool":{
"must":[
{"term":{"name":"coco"}},
{"term":{"age":21}}
]
}
}
]
}
}
}
范围过滤:
gte:>=(大于等于)
gt:>(大于)
lte:<=(小于等于)
lt:<(小于)
# 范围过滤,取age>20 and age<23的数据
GET /demo/user/_search
{
"post_filter":{
"range":{
"age":{
"gt":20,
"lt":23
}
}
}
}
# 过滤非空,取name is not null 的数据
GET /demo/user/_search
{
"query":{
"bool":{
"filter":{
"exists":{
"field":"name"
}
}
}
}
}
检索词频率TF(Term Frequency)对搜索结果排序的影响。
检索词频率:检索词在该字段出现的频率越高相关性也越高,字段中出现过多次要比一次相关性高。
constant_score:将query与filter包装,消除TF对搜索结果排序的影响。
GET /demo/user/_search
{
"query":{
"constant_score":{
"filter":{
"exists":{
"field":"name"
}
}
}
}
}
ElasticSearch提供了一种特殊的缓存,即过滤器缓存(filter cache),用来存储过滤器的结果,被缓存的过滤器并不需要过多的内存(因为它们只存储了哪些文档能与过滤器相匹配的相关信息),
而且可以供后续所有与之相关的查询重复使用,从而极大的提高了查询的性能。
ElasticSearch默认缓存的过滤器:
exists,missing,range,term,terms。
ElasticSearch默认不缓存的过滤器:
numeric_range,script,geo_bbox,geo_distance,geo_distance_range
geo_polygon,geo_shape,and,or,not
开启方式:在filter查询语句后加上"_catch":true
sum:求总数值,等同sum()
# 聚合name=kevin的age,等同:name=kevin,sum(age)
GET /demo/user/_search
{
"size":0,
"aggs":{
"age_of_sum":{
"sum":{
"field":"age"
}
}
},
"query":{
"term":{
"name":"kevin"
}
}
}
# "size":0,不展示原始数据,数值设为多少展示几条,不设置默认全部展示
min:求最小值,等同min()
#聚合查询,获取最小的年龄,等同min(age)
GET /demo/user/_search
{
"size":0,
"aggs":{
"age_of_min":{
"min":{
"field":"age"
}
}
}
}
max:求最大值,等同max()
#聚合查询,获取最大的年龄,等同max(age)
GET /demo/user/_search
{
"size":0,
"aggs":{
"age_of_max":{
"max":{
"field":"age"
}
}
}
}
avg:求平均值,等同avg()
#聚合查询,获取平均的年龄值,等同avg(age)
GET /demo/user/_search
{
"size":0,
"aggs":{
"age_of_avg":{
"avg":{
"field":"age"
}
}
}
}
cardinality:求基数,等同count()
# 求基数,求age有多少个数据,等同count(age)
GET /demo/user/_search
{
"size":0,
"aggs":{
"age_of_cardinality":{
"cardinality":{
"field":"age"
}
}
}
}
terms:分组,等同group by
# 分组,根据age进行分组,等同group by age
GET /demo/user/_search
{
"size":0,
"aggs":{
"age_group_by":{
"terms":{
"field":"age"
}
}
}
}
嵌套聚合查询案例
# 嵌套聚合,获取name=kevin,根据age做分组,再根据已平均的年龄做排序,等同:name=kevin,group by age,order by avg(age)
GET /demo/user/_search
{
"query":{
"match":{
"name":"kevin"
}
},
"size":0,
"aggs":{
"age_group_by":{
"terms":{
"field":"age",
"order":{
"avg_of_age":"desc"
}
},
"aggs":{
"avg_of_age":{
"avg":{
"field":"age"
}
}
}
}
}
}
将多个基本查询组合成单一查询的查询
参数:
must:文档必须匹配这些条件才能被包含进来。
must_not:文档必须不匹配这些条件才能被包含进来。
should:如果满足这些语句的任意语句,将增加_score,否则无任何影响,主要用于修正每个文档的相关性得分。
filter:必须匹配,但它以不评分、过滤模式来进行,这些语句对评分没有贡献,只是根据过滤标准来排除或包含文档。
相关性得分是如何组合的,每一个子查询都独自地计算文档的相关性得分,一旦得分被计算出来,bool查询就将这些得分进行合并并返回一个代表整个布尔操作的得分。
案例:
# 标识查找remark包含我是kevin的词,并且age<>21,
# should,sex=男或create_time>=2020-05-03的可以被匹配也可以不被匹配,如果匹配排名更高
GET /demo/user/_search
{
"query":{
"bool":{
"must":{"match":{"remark":"我 是 kevin"}},
"must_not":{"match":{"age":21}},
"should":[
{"match":{"sex":"男"}},
{"range":{"create_time":{"gte":"2020-05-03"}}}
]
}
}
}
改写案例:不让创建时间影响得分
# 标识查找remark包含我是kevin的词,并且age<>21,
# should,sex=男可以被匹配也可以不被匹配,如果匹配排名更高
# 避免create_time影响得分,将其过滤
GET /demo/user/_search
{
"query":{
"bool":{
"must":{"match":{"remark":"我 是 kevin"}},
"must_not":{"match":{"age":21}},
"should":[
{"match":{"sex":"男"}}
],
"filter":{
"range":{"create_time":{"gte":"2020-05-03"}}
}
}
}
}
通过将range查询移到filter,转成不评分的查询,将不再影响文档相关排名。
由于上一个案例是不评分的查询,可以使用各种对filter查询有效的优化来提升性能。
bool查询本身也可以被用做不评分的查询,简单地将它放置到filter语句中并在内部构建布尔逻辑。
# 标识查找remark包含我是kevin的词,并且age<>21,
# should,sex=男可以被匹配也可以不被匹配,如果匹配排名更高
# 过滤为false的,create_time>=2020-05-03,且age<=25,并name<>'coco'
GET /demo/user/_search
{
"query":{
"bool":{
"must":{"match":{"remark":"我 是 kevin"}},
"must_not":{"match":{"age":21}},
"should":[
{"match":{"sex":"男"}}
],
"filter":{
"bool":{
"must":[
{"range":{"create_time":{"gte":"2020-05-03"}}},
{"range":{"age":{"lte":25}}}
],
"must_not":[
{"term":{"name":"coco"}}
]
}
}
}
}
}
constant_score:将一个不变的常量评分应用于所有匹配的文档。
使用场景:常用于只需要执行一个filter而没有其它查询(例如评分查询)的情况。
term查询被放置在constant_score中,转成不评分的filter,这种方式可以用来取代只有filter语句的bool查询。
GET /demo/user/_search
{
"constant_score":{
"filter":{
"term":{
"name":"coco"
}
}
}
}