大家好,我是考100分的小小码 ,祝大家学习进步,加薪顺利呀。今天说一说Elasticsearch查询过滤解惑,希望您对编程的造诣更进一步.
简介
之前一直被查询(query)与过滤(filter)所困惑,为什么同样是bool在一个地方就是查询,在另一个地方就是过滤了。
后来仔细的看了一下官方文档才发现,都是查询,只是区分:
- query context(查询上下文)
- filter context(过滤上下文)
为什么要区分query context与filter context呢?
因为效率不同,在 filter context中的查询更加高效,因为filter context不会计算相关性评分,并且ES会自动缓存高频过滤查询。
哪些是过滤上下文
首先看到filter肯定是了,另外在bool查询中的must_not也会在filter context中执行。
filter
bool查询:
{
"query": {
"bool": {
"filter": [
{ "term": { "status": "1" }},
{ "range": { "create_date": { "lte": "2020-01-01" }}}
]
}
}
}
constant_score查询:
{
"query": {
"constant_score" : {
"filter" : {
"term" : { "user" : "tim"}
},
"boost" : 1.2
}
}
}
聚合函数中:
{
"aggs" : {
"month" : {
"filter" : { "term": { "type": "2" } }
}
}
}
must_not
{
"query": {
"bool" : {
"must_not" : {
"range" : {
"age" : { "gte" : 18, "lte" : 30 }
}
}
}
}
}
bool查询
类型 | 说明 |
---|---|
must | 表示条件必须满足,多个条件之间的关系是and,表示同时满足 |
should | 表示至少匹配一个,多个条件之间的关系是or,表示至少满足一个 |
filter | 条件必须满足,和must不同,filter在过滤上下文执行,不计算相关性得分 |
must_not | 条件必须不满足,在过滤上下文执行,不计算相关性得分 |
注意:must_not是在filter context(过滤上下文执行)
{
"query": {
"bool" : {
"must" : {
"term" : { "status" : 1 }
},
"filter": {
"term" : { "type" : "Component" }
},
"must_not" : {
"range" : {
"ctime" : { "gte" : "2019-12-01", "lte" : "2020-01-01" }
}
},
"should" : [
{ "term" : { "tag" : "Kafka" } },
{ "term" : { "tag" : "Elasticsearch" } }
]
}
}
}
如上所示,term表示term查询,表示精确匹配,range查询是范围匹配。
上面的查询的含义是,文档中status字段必须为1,type字段必须是”Component”,ctime字段必须在2019-12-01到2020-01-01这个范围之内,tag字段必须包含”Kafka”或者”Elasticsearch”。
全文搜索查询
match
match最常用,做的就是对应字段的全文索引。
{
"match" : {
"lauguage" : "Java"
}
}
{
"query": {
"match" : {
"message" : {
"query" : "java python ruby"
}
}
}
}
multi_match
multi_match和match差不多,但是可以指定多个字段搜索。
{
"query": {
"multi_match" : {
"query": "java python ruby",
"fields": [ "subject", "message" ]
}
}
}
match_all
match_all可以查询到所有索引字段,没有查询条件下的默认使用match_all。
{
"match_all" : {}
}
match_phrase
match_phrase和match有点相似,但是有2点很大区别:
- 查询分词的单词必须要在文档相应字段分词中全部出现
- 单词出现的顺序也必须一致
{
"query": {
"match_phrase" : {
"message" : "java python ruby"
}
}
}
出现相对位置可以使用slop参数调整
{
"query": {
"match_phrase": {
"message": {
"query": "java python ruby",
"slop": 2
}
}
}
}
可以参考下面的查询示例,下面是测试数据:
如上图所示,是没有slop参数的查询结果。
如上图所示,是slop参数为2的查询结果。
如上图所示,是slop参数为3的查询结果。
我们可以看到,slop参数就是调整查询单词中能间隔slop-1个单词。
match_phrase_prefix
match_phrase_prefix和match_phrase差不多,但是运行前缀匹配
{
"query": {
"match_phrase_prefix" : {
"message" : {
"query" : "java python r"
}
}
}
}
其他常用查询
出来我们上面介绍的bool查询、全文搜索查询以及涉及到的term、range等查询,我们还有一些其他常用的查询,下面我们就简单的介绍一下。
terms
前面我们已经有提到term查询,表示精确匹配,terms和term基本一样,但是terms允许设置多个值,只要有一个值精确匹配就算匹配成功。
{
"query" : {
"terms" : {
"component" : ["kafka", "elasticsearch"],
"boost" : 1.5
}
}
}
如上所示,表示只要component字段中精确匹配到kafka 或者 elasticsearch就算匹配成功。
boost影响文档相关性,大于1表示计算时增加文档相关性,小于1表示计算时减小文档相关性。
terms_set
terms_set查询是给定一个数组,如果文档中的对应字段包含至少指定个值在参数数组中就匹配。
听起来有点绕,没有关系,我们看一个示例,先创建一个user索引,然后添加2个文档如下。
PUT /user/_doc/1?refresh
{
"name": "tim",
"hobby": ["看书", "跑步"],
"required_matches": 2
}
PUT /user/_doc/2?refresh
{
"name": "allen",
"hobby": ["看书", "冥想"],
"required_matches": 2
}
下面我们就可以执行terms_set查询了。 GET /user/_search
{
"query": {
"terms_set": {
"hobby.keyword": {
"terms": ["看书", "游泳", "冥想"],
"minimum_should_match_field": "required_matches"
}
}
}
}
如上所示,查询中使用的是hobby.keyword,而不是hobby,是因为添加user映射的时候没有设置mapping,自动映射hobby为text类型,但是自动映射还使用了fields参数,所以我们可以使用hobby.keyword来搜索。
如果怕麻烦,可以直接设置一下mapping,把hobby设置为keyword类型。
上面的搜索会查询到name为allen的文档,如果我们把”冥想”换成”跑步”就会搜索到name为tim的文档。
感觉比较蛋疼的是最小匹配个数要在文档中设置,而不是直接在查询中设置值,在查询中使用的是引用文档中最小匹配的字段
exists
{
"query": {
"exists": {
"field": "gid"
}
}
}
ids
{
"query": {
"ids" : {
"values" : ["1", "3", "5", "7", "9"]
}
}
}
prefix
前缀匹配有时候非常有用,比如说我们要找老王:
{
"query": {
"prefix" : { "name" : "王" }
}
}
wildcard
如果觉得prefix前缀查询还不能满足你的需求,那还可以考虑通配符查询。
{
"query": {
"wildcard": {
"name": {
"value": "王*五",
"boost": 1.5
}
}
}
}
wildcard支持2个通配符:
- ?表示匹配一个字符
- *匹配0到多个字符
boost的值可以影响相关性,小于1表示减小文档的相关性,大于1表示增加文档的相关性。
如果通配符还不满足需求,那还可以考虑regexp正则表达式查询
但是,强烈推荐线上环境只使用prefix,如果要希望影响评分相关性,那使用wildcard也不要以通配符开头。
constant_score
用时候我们只想过滤,就可以考虑constant_score查询:
{
"query": {
"bool": {
"must": {
"match_all": {}
},
"filter": {
"term": {
"status": 1
}
}
}
}
}
等价于:
{
"query": {
"constant_score": {
"filter": {
"term": {
"status": 1
}
}
}
}
}
文档
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
转载请注明出处: https://daima100.com/6749.html