目录
虽然工作中一直有用到es,但是每次都没有深入了解,都是浅浅的用一下,就导致出了问题后,很难发现,很难解决。比如,前几天就因为用错了term和terms看了老半天都看不出原因。所以,我痛定思痛,又开始学习es了(也是一些浅浅的学习)
一. 索引
?pretty是为了让输出格式更好看一点
?v:输出字段的title
简单创建索引
DELETE /user
PUT /user
POST user/_doc/1
{
"name":"zhang san",
"sex":"male",
"age":18,
"birth":"2000-12-12",
"hobby":["read","song","movie"],
"desc":"happy boy"
}
这样,添加一条数据后,就会创建一个索引结构:
其中,字符串会默认创建text类型字段,数字会默认创建long类型字段,日期格式会创建date类型字段
text类型的字段,会自动创建keyword字段。keyword不进行分词,用于精准匹配;text类型的字段会被分词
比如,desc字段会被分词,而desc.keyword字段不会进行分词
二. 查询
我感觉查询就是很复杂,之前写的dsl都是按照别人写的,照葫芦画瓢,写个差不多,然后发现能用,就不再管了, 还是要好好学习呀
1. 上下文
GET user/_search
查询结果如下:
took:请求花费时长
timed_out: 是否超时
_shards:请求分片情况
hits:真正的结果
_source:元数据
_score:评分
2. 相关度评分
查询结果的排序默认按照相关度评分排序,评分越高,排名越靠前
3. 元数据
_source中的值就是元数据
4. 查询全部
这两个都是查询全部
其中 GET user/_search 相当于 select * from user
GET user/_search
{
"query":{
"match_all":{}
}
}
相当于 select * from user where 1=1;
GET user/_search
GET user/_search
{
"query":{
"match_all":{}
}
}
5. 禁用score
不展示元数据,只展示id,节省存储开销
GET user/_search
{
"_source": false,
"query":{
"match_all":{}
}
}
结果如下:
禁用source的优缺点:
也可以在创建索引时,就设置查询时包含哪些字段,不包含哪些字段
PUT user2
{
"mappings":{
"_source":{
"includes":[], // 查询时包含哪些字段
"excludes":[] // 查询时不包含哪些字段
}
}
}
6. 指定source
可以通过指定source来返回字段,相当于select name from user where 1=1
GET user/_search
{
"_source": "name",
"query":{
"match_all":{}
}
}
source支持数组,也支持通配符 filed1.* ["",""],
也可以通过includes和exclueds来指定结果包含哪些字段,不包含哪些字段
GET user/_search
{
"_source": {
"includes":[],
"exclueds":[]
}
"query":{
"match_all":{}
}
}
includes和exclueds冲突,以exclueds为准
7. 带参查询
带参查询:
GET user/_search?q=name:xxx
分页查询:
GET user/_search?from=0&size=10&sort=xxx:asc
精准匹配 (查询name包含xxx的)
GET user/_search?q=name:xxx
查询所有创建索引字段中包含xxx的
GET user/_search?q=xxx
三、macth查询 (搜索词会被分词)
1. macth
match是包含的意思,分词查询
GET user/_search
{
"query":{
"match":{
"name":"xiao"
}
}
}
查询name中包含xiao的,其中xiao ming的xiao mei都包含,因为name的text类型的字段,会对name中的空格进行分词,比如xiao ming,会被分词为xiao 和ming,其中xiao就符合name:xiao,所以就能查到这条数据
简单演示一下分词(因为英文的分词基本都是以空格进行分词,这里图省事都没有用中文)
GET user/_analyze
{
"analyzer": "standard",
"text": "xiao ming"
}
2. multi_match (用于多字段匹配)
GET user/_search
{
"query":{
"multi_match":{
"query":"li si",
"fields":["name","desc"]
}
}
}
查询name或者desc字段中包含li或者si的结果
3. match_phrase(用于短语匹配)
短语中的词不会被分词
查询包含aa和bb的,并且顺序不能乱(aa bb是一体的)
GET user/_search
{
"query":{
"match_phrase":{
"desc":"li si"
}
}
}
四、精确查询(搜索词不会被分词)
1. term
精准匹配, 匹配和搜索词项完全相等的结果,不进行分词
这样没有结果,是因为 desc中的li si会被分词为li 和si,term不进行分词,所以需要查询完整的li si,所以查不到结果, 下面的name.keyword不会进行分词,所以就能查到了
2. terms
terms用法与term基本相同, 区别在于terms查询可以用于数组
GET user/_search
{
"query":{
"terms":{
"hobby":["running","song"]
}
}
}
3. range
范围查询
GET user/_search
{
"query":{
"range":{
"age":{
"gte":18,
"lte":20
}
}
}
}
查询age>=18 and age <=20的结果
也可以用于日期
其中,
now-1d/d 前一天
now/d 今天
time_zone:可以设置时区
五、过滤器 filter
filter是以结果为导向, query是以过程为导向
query进行相关度评分, filter不进行相关度评分,每一条数据得分都是1.0
filter有缓存机制, 性能比query强
filter嵌套在constant_score中,默认评分是1.0,也可以指定评分
GET user/_search
{
"query":{
"constant_score":{
"filter":{
"match":{
"name":"li si"
}
}
}
}
}
指定评分,所有评分都是1.2
constant_scorehe bool都能嵌套filter,bool下面说
六、 bool
bool用于组合查询,可以将must、filter、should、must_not进行组合查询,must和should会参与计算相关度评分,filter和must_not不计算相关度评分
must:必须全部满足,相当于and
filter:过滤
should: 相当于or
must_not:必须不满足相当于!=
1. must
匹配name包含li si的,并且desc包含boy的
GET user/_search
{
"query":{
"bool":{
"must":[
{
"match":{
"name":"li si"
}
},
{
"match":{
"desc":"boy"
}
}
]
}
}
}
2. filter
同must,只是没有相关度评分(为0)
GET user/_search
{
"query":{
"bool":{
"filter":[
{
"match":{
"name":"li si"
}
},
{
"match":{
"desc":"boy"
}
}
]
}
}
}
3. must_not
匹配都不包含的结果,name不包含li si,desc不包含boy,也不进行相关度评分
GET user/_search
{
"query":{
"bool":{
"must_not":[
{
"match":{
"name":"li si"
}
},
{
"match":{
"desc":"boy"
}
}
]
}
}
}
4. should
should相当于or,其中满足一条就能查询出来,会进行相关度评分
GET user/_search
{
"query":{
"bool":{
"should":[
{
"match":{
"name":"li si"
}
},
{
"match":{
"desc":"boy"
}
}
]
}
}
}
当查询中包含filter或者must,should中满足条件的个数可以为0
可以通过设置minimum_should_match来控制should中的条件至少应该满足几个
当没有设置 minimum_should_match时,第二条数据没有满足should中的条件
设置了minimum_should_match=1后,要求should中至少要有一条满足条件,所以只有一条结果了
*** 复杂的是,每个查询中都可以再嵌套bool
GET user/_search
{
"query":{
"bool":{
"filter":[
{
"match":{
"name":"li"
}
},
{
"match":{
"hobby":"song"
}
}
],
"should":[
{
"match":{
"age":"17"
}
},
{
"bool":{
"must":[
{
"match":{
"sex":"male"
}
}
]
}
}
],
"minimum_should_match":1
}
}
}
这样,should中的两个条件满足一个就可以了,所以结果又多了一条
最后:查询所有索引可以用 GET _search