ES中提供了一种强大的检索数据方式,这种检索方式称之为Query DSL
,Query DSL
是利用Rest API传递JSON格式的请求体(Request Body)数据与ES进行交互,这种方式的丰富查询语法让ES检索变得更强大,更简洁。
用一个例子说明它们之间的区别
i like eating and cooking
默认分词器应该将内容分为 “i
” “like
” “eating
” “and
” “kuing
”查询词/匹配类型 | match | m_phrase | m_p_prefix |
---|---|---|---|
i | ✅ | ✅ | ✅ |
i like | ✅ | ✅ | ✅ |
i like singing | ✅ | ❌ | ❌ |
i like ea | ✅ | ❌ | ✅ |
and | ✅ | ✅ | ✅ |
总结:
match
会将搜索词分词后再去匹配,match_phrase
和match_phrase_prefix
不会将搜索词分词match
和match_phrase
属于精准匹配,match_phrase
要求搜索词与字段内容有序连贯的匹配match_phrase_prefix
不属于精准匹配,它在match_phrase
的基础上,允许最后一个词使用前缀匹配term关键字:使用关键词查询
keyword
类型的字段时,需要全部内容匹配上所以除了text类型,其余类型均不分词
es中默认使用的是标准分词器,中文单字分词 ,英文 单词分词
#查询语句
GET /products/_search
{
"query": {
"term": {
"title": {
"value": "猪猪侠"
}
}
}
}
#结果
"hits" : {
"total" : {
"value" : 1,
"relation" : "eq"
},
"max_score" : 1.2039728,
"hits" : [
{
"_index" : "products",
"_type" : "_doc",
"_id" : "rj5iCYABiB8dDekOlCwE",
"_score" : 1.2039728,
"_source" : {
"id" : 2,
"title" : "猪猪侠",
"price" : 0.5,
"created_at" : "2022-04-08",
"description" : "5毛钱一包"
}
}
]
}
range关键字:用来查询指定范围内的文档
#范围查询 range
GET /products/_search
{
"query": {
"range": {
"字段名": {
"gte": 2, #下界
"lte": 4 #上界
}
}
}
}
prefix关键字:按照文档的前缀进行查询
#前缀查询 prefix
GET /products/_search
{
"query": {
"prefix": {
"FIELD": {
"value": ""
}
}
}
}
可使用通配符查询:
?
匹配一个字符*
匹配多个字符#通配符查询
GET /products/_search
{
"query": {
"wildcard": {
"FIELD": {
"value": "VALUE"
}
}
}
}
通过一个id数组去查询文档
#通过一组id查询
GET /products/_search
{
"query": {
"ids": {
"values": [1,2]
}
}
}
模糊查询含有指定关键字的文档
注意: fuzzy 模糊查询 最大模糊错误 必须在0-2之间
GET /products/_search
{
"query": {
"fuzzy": {
"FIELD": "xxxx"
}
}
}
Elasticsearch可以使用bool 关键字用来组合多个条件实现复杂查询,类似于在SQL中使用AND
、OR
以及NOT
的运算
Elasticsearch支持的布尔逻辑类型包括有以下几种:
类型包括有以下几种:
must
:文档必须符合其中所有的查询条件,包含多个条件时类似于SQL中的AND
,运算符中的&&
should
:文档必须符合其中任意一个及以上查询条件(可由minimum_should_match
指定需要满足的条件数量),包含多个条件时类似于SQL中的OR
,运算符中的||
must_not
:文档必须不符合其中所有的查询条件,类似于SQL中的NOT
,且不参与分值的计算,返回的分支都是0
filter
::先筛选出符合条件的文档,并且不计算得分。一般情况下,我们应该先使用过滤操作过滤掉一部分数据,然后使用查询去精准匹配数据,提高查询效率
当使用must
查询时,文档必须符合其中包括的所有查询条件。
{
"query": {
"bool": {
"must": [
"term": {
"age": 20
}
]
}
}
}
该查询等同于下面对应的SQL
语句
SELECT * FROM xxx WHERE age = 20;
使用must
时可以同时指定多个查询条件,在DSL中它以数组的形式表示,效果类似于SQL中的AND
运算。例如下面的例子:
{
"query": {
"bool": {
"must": [
{ "term": { "age": 20 } },
{ "term": { "gender": "male" } }
]
}
}
}
should
查询类似于SQL中的OR
语句,当其中包括两个及两个以上的条件时,其查询的结果必须至少满足其中一个。当只有一个查询条件时,即结果必须满足该条件。
{
"query": {
"bool": {
"should": [
{ "term": { "age": 20 } },
{ "term": { "gender": "male" } },
{ "range": { "height": { "gte": 170 } } },
]
}
}
}
该查询等同于下面对应的SQL语句:
SELECT * FROM xxx WHERE age = 20 OR gender = "male" or height >= 170;
should
查询与SQL中的OR
运算较为不同的一点是,should
查询可以使用minimum_should_match
参数指定至少需要满足几个条件。例如下面的例子中,查询的结果需要满足两个或两个以上的查询条件:
{
"query": {
"bool": {
"should": [
{ "term": { "age": 20 } },
{ "term": { "gender": "male" } },
{ "term": { "height": 170 } },
],
"minimum_should_match": 2
}
}
}
在同一个bool
语句中若不存在must
或filter
时,minimum_should_match
默认的值为1,即至少要满足其中一个条件;但若有其它must
或filter
存在时,minimum_should_match默认值为0。就是说should查询会默认失效
例如下面的查询,所有返回的文档age值必定为20,但其中可能包括有status值不为"active"的文档。若需要二者同时生效,可入上面例子中一样在bool查询中增加一个参数"minimum_should_match": 1。
{
"query": {
"bool": {
"must": {
"term": {
"age": 20
},
},
"should": {
"term": {
"status": "active"
}
},
"minimum_should_match": 1
}
}
}
must_not
查询类似于SQL语句中的NOT
运算,它将只返回不满足指定条件的文档。例如:
{
"query": {
"bool": {
"must_not": [
{ "term": { "age": 20 } },
{ "term": { "gender": "male" } }
]
}
}
}
该查询等同于下面的SQL查询语句(由于MySQL不支持下面语句使用NOT,于是改写为使用!=
实现):
SELECT * FROM xxx WHERE age != 20 AND gender != "male";
另外,must_not
与filter
相同,采用过滤器执行而不需要计算文档的得分,所以返回的结果对应的分值为0。
使用filter
查询时其效果等同于must
查询,但不同于must
查询的是,先筛选出符合条件的文档,并且不计算得分
例如下面的查询中,将返回所有status
的值为"active"
的文档,其得分均为0.0
。
{
"query": {
"bool": {
"filter": {
"term": {
"status": "active"
}
}
}
}
}
我们也可以在各个查询中进行嵌套查询。但需要注意的是,布尔查询必须包含在bool
查询语句中,所以在嵌套查询中必须在内部再次使用bool
查询语句。
{
"query": {
"bool": {
"must": [
{
"bool": {
"should": [
{ "term": { "age": 20 } },
{ "term": { "age": 25 } }
]
}
},
{
"range": {
"level": {
"gte": 3
}
}
}
]
}
}
}
该查询语句等同于以下SQL语句:
SELECT * FROM xxx WHERE (age = 20 OR age = 25) AND level >= 3;
会先将查询条件分词之后,再单独的拿去查询
比如说泡面,会分成“泡”和“面”然后单独拿去查询
GET /products/_search
{
"query": {
"multi_match": {
"query": "泡面",
"fields": ["title","description"]
}
}
}
GET /products/_search
{
"query": {
"query_string": {
"default_field": "description",
"query": "xxxx"
}
}
}
可以让符合条件的文档中的关键词高亮
*
表示匹配所以字段GET /products/_search
{
"query": {
"term": {
"description": {
"value": "泡面"
}
}
},
"highlight": {
"fields": {
"*":{}
}
}
}
自定义高亮html标签: 可以在highlight中使用
pre_tags
和post_tags
GET /products/_search
{
"query": {
"term": {
"description": {
"value": "xxx"
}
}
},
"highlight": {
"post_tags": [""],
"pre_tags": [""],
"fields": {
"*":{}
}
}
}
多字段高亮 使用
require_field_match
开启多个字段高亮
GET /products/_search
{
"query": {
"term": {
"description": {
"value": "xxx"
}
}
},
"highlight": {
"require_field_match": "false",
"post_tags": [""],
"pre_tags": [""],
"fields": {
"*":{}
}
}
}
size 关键字: 指定查询结果中返回指定条数。 默认返回值10条
GET /products/_search
{
"query": {
"match_all": {}
},
"size": 5
}
from 关键字: 用来指定起始返回位置,和size关键字连用可实现分页效果
GET /products/_search
{
"query": {
"match_all": {}
},
"size": 5,
"from": 0 #(page-1)*
}
GET /products/_search
{
"query": {
"match_all": {}
},
"sort": [
{
"price": {
"order": "desc"
}
}
]
}
_source 关键字: 是一个数组,在数组中用来指定展示那些字段
GET /products/_search
{
"query": {
"match_all": {}
},
"_source": ["title","description"]
}
倒排索引也叫反向索引,有正向就有反向。正向索引就是通过key去找value,反向索引则是通过value找key。
ES底层在检索时,底层使用的就是反向索引
测试用例
现有索引和映射如下:
{
"products" : {
"mappings" : {
"properties" : {
"description" : {
"type" : "text"
},
"price" : {
"type" : "float"
},
"title" : {
"type" : "keyword"
}
}
}
}
录入如下数据
_id | title | price | description |
---|---|---|---|
1 | 蓝月亮洗衣液 | 19.9 | 蓝月亮洗衣液很高效 |
2 | iphone13 | 19.9 | 很不错的手机 |
3 | 小浣熊干脆面 | 1.5 | 小浣熊很好吃 |
可视化表示