美文网首页
ES 查询语法解析之Query DSL — 文章很长,慎入

ES 查询语法解析之Query DSL — 文章很长,慎入

作者: 右耳菌 | 来源:发表于2022-11-11 23:27 被阅读0次

本文以6.8版本为例

1. Query DSL

1.1 Query and Filter context

其实其本质就是两个内容,一个是Query context,顾名思义就是查询上下文,其返回的内容会包含该文档与查询的上下文有多匹配,如这句话的描述“how well does this document match this query clause?”,当然其中也会返回一个匹配得分“_score”; 另外一个是Filter context,中文叫做过滤上下文,其实本质就是过滤用的,其返回的内容会包含该文档是否符合这个查询,如下面这句话的描述“Does this document match this query clause?”, 具体可以查看上边的英文描述,看不懂就翻译一下吧。
例子
# 其中的query包含的是查询上下文,而filter包含的是过滤上下文。
GET /_search
{
  "query": { 
    "bool": { 
      "must": [
        { "match": { "title":   "Search"        }},
        { "match": { "content": "Elasticsearch" }}
      ],
      "filter": [ 
        { "term":  { "status": "published" }},
        { "range": { "publish_date": { "gte": "2015-01-01" }}}
      ]
    }
  }
}

1.2 Match All Query

其实这个模块包含了两个内容:

  • Match All Query
    据官网的描述,它说的是这个是最简单的查询了,这个查询会匹配所有的文档,且将所有返回的文档的匹配得分设置为1.0,当然也可以通过设置boost,修改这个返回的得分。

  • Match None Query
    与Match All Query 相反,这个将不会匹配任何的文档。

  • 例子:

# match all query
GET /_search
{
    "query": {
        "match_all": {}
    }
}

GET /_search
{
    "query": {
        "match_all": { "boost" : 1.2 }
    }
}

# match none query
GET /_search
{
    "query": {
        "match_none": {}
    }
}

1.3 Full text queries

用于搜索被分词后的text类型字段,查询字符串会用索引数据时相同的analyzer对其进行解析。

  1. Match query

即默认情况下,下面的查询并不只是查询到了含有这句歌词的文档,而是分词器在对All I need is someone who makes me wanna sing进行分词后,凡是匹配其中的任意一个内容的情况下都会匹配成功,这是因为其使用了 "or" 的匹配逻辑。

GET /songs_v1/_search
{
  "query": {
    "match": {
      "lyrics": "All I need is someone who makes me wanna sing"
    }
  }
}

如果要解决这个问题,就需要将or修改成and,此时,将只会匹配包含有All I need is someone who makes me wanna sing这句歌词的文档。

GET /songs_v1/_search
{
  "query": {
    "match": {
      "lyrics": {
        "query": "All I need is someone who makes me wanna sing",
        "operator": "and"
      }
    }
  }
}

此外match query还可以通过fuzziness进行模糊匹配的配置,即可以配置有多少个字母不一样的情况。下面是允许有一个字母不一样的情况

GET /songs_v1/_search
{
  "query": {
    "match": {
      "lyrics": {
        "query": "All I need is somene who makes me wanna sing",
        "operator": "and",
        "fuzziness": 1
      }
    }
  }
}
  1. Match Phrase Query:短语匹配查询

试想一种情况:
有一句歌词take me to your heart,如果我们想要使用take me匹配的话,如果直接用match query + and 的话的确可以匹配出来结果,但是take me却有可能是分隔开的,此时如果使用match_phrase,就可以确保成功了。

GET /songs_v1/_search
{
  "query": {
    "match_phrase": {
      "lyrics": {
        "query": "take me"
      }
    }
  }
}

而如果有一种情况,就是我知道有take这个单词且两个还是三个单词之后有一个your,但是中间的我忘了,那么要如何进行查询呢?其实也很简单。集合使用slop即可,但是注意哦,如果这里将slop设置为1,是无法匹配成功的哦。

GET /songs_v1/popular/_search
{
  "query": {
    "match_phrase": {
      "songName": {
        "query": "take your ",
        "slop": 3
      }
    }
  }
}
  1. Match Phrase Prefix Query

    顾名思义啦,就是短语前缀匹配,前缀懂吧?嗯嗯,就那个前缀。例子如下所示,其实就是如果分词后的某个短语是以提供的短语开头的就能匹配上(我觉得是这个意思,如果不对,欢迎指正)。
#match phrase prefix query
GET /songs_v1/_search
{
  "query": {
    "match_phrase_prefix": {
      "songName": "take me"
    }
  }
}
  1. Multi Match Query

    即可以同时对多个字段进行查询,没啥解释的,直接上例子,(注:也可以使用通配符如*等,具体查看官网):
#multi match query
GET /songs_v1/_search
{
  "query": {
    "multi_match": {
      "query": "take me to your heart",
      "fields": ["songName", "lyrics"]
    }
  }
}
  1. Common Terms Query:常用术语查询
  • 问1、什么是停用词?索引时做停用词处理的目的是什么?
    答:如常见的英文中的 his 、her、my、mine,中文的 他、她、它、地等等。因为这些词出现的频率太多了

  • 问2、如果在索引时应用停用词处理,下面的两个查询会查询什么词项?
    the brown fox: 会得出 brown fox 的结果
    not happy: 会得出happy

结论:索引时应用停用词处理会影响查询精度?若不做停用词处理,会应向查询,如何协调这两个问题呢?

Common terms query会区分高频词、低频词,我们可以通过cutoff_frequency来指定一个分界值,将搜索文本中的词分为高频词和低频词,低频词的重要性高于高频词。

先对低频词进行搜索,并计算所有匹配文档相关性得分;
再搜索和高频词匹配的文档,这会搜到很多文档,不计算得分
取交集,交集中的文档进行高频词得分计算
高频词的得分和低频词得分相加,作为文档得分。实际执行的搜索是必须包含低频词+或包含高频词。

思考:这样处理下,如果用户输入的都是高频词如“to be or not to be”结果会是怎样的?你希望是怎样的?
解决办法:如果都是高频词,让用户可以自己定对高频词做and/or操作,目己定对低频词进行and/or操作;或指定最少得多少个同时匹配。

#Common terms query

GET /songs_v1/_search
{
    "query": {
        "common": {
            "message": {
                "query": "take me to your heart",
                # 出现的百分比,如果高于则为高频词,反之则是低频词,也可以是整数,此时表示出现次数
                "cutoff_frequency": 0.001,  
                # 对低频词做or操作,也可以设置为and操作
                "low_freq_operator" : "or", 
                # 对高频词做or操作,也可以设置为and操作                
                "high_freq_operator" : "or",
                # 表示最低需要匹配多少个才是相关的
                "minimum_should_match": {
                  "high_freq": 2,
                  "low_freq": 2
                }
            }
        }
    }
  1. Query String Query

    可以使用lucene的语法进行搜索
#Query String query
GET /bank/_search
{
    "query": {
        "query_string" : {
            "default_field" : "content",
            "query" : "address:(green OR street) AND gender:F"
        }
    }
}
  1. Simple Query String Query

    下图表示不同的字符组合表示什么意思,还是挺重要的哦:
  • 例子:
#Simple uery String query
GET /bank/_search
{
    "query": {
        "simple_query_string" : {
            "fields" : ["address"],
            "query" : "street*"
        }
    }
}

1.4 Term-level queries
  1. Term Query

其实只要记住一点,它不会对查询串进行分词,所以一般查询的时候要搭配XXXX.keyword进行,其他的特点请查看官网比较好。

#term query
GET /bank/_search
{
  "query": {
    "term": {
      "_id": {
        "value": "50"
      }
    }
  }
}

GET /bank/_search
{
  "query": {
    "term": {
      "firstname.keyword": {
        "value": "Aurelia"
      }
    }
  }
}
  1. Terms Query

与term查询基本一致,不过可以对多个词进行查询

# terms query
# 例子1
GET /bank/_search
{
  "query": {
    "terms": {
      "age": [
        40,
        33
      ]
    }
  }
}

# 例子2
GET /bank/_search
{
  "query" : {
    "terms" : {
      "address.keywor创":[
        "806 Rockwell Place",
        "502 Baycliff Terrace"
      ]
    }
  }
}

当然还有其他的用法,如terms lookup


例子:
#这个例子表示要查询在tweets中user在 索引为users下的id为2的doc中followers的人。
GET /tweets/_search
{
    "query" : {
        "terms" : {
            "user" : {
                "index" : "users",
                "type" : "_doc",
                "id" : "2",
                "path" : "followers"
            }
        }
    }
}

#另一个例子
#Terms lookup
#类比
# select * from bank where city in ( select city_id from citys );
GET /bank/_search
{
  "query": {
    "terms": {
      "age":{
        "index" : "bank",
        "type" : "account",
        "id" : "6",
        "path" : "age"
      }
    }
  }
}
  1. Range Query

即范围查询:

  • 例子:
# range query
# >= 20 <=30
GET /bank/_search
{
  "query": {
    "range": {
      "age": {
        "gte": 20,
        "lte": 30
      }
    }
  }
}
  1. Exists Query

    即查询某个字段不为null或者[]的文档:
  • 例子:
#exists  query 

GET /bank/_search
{
  "query": {
    "exists": {
      "field": "numbers"
    }
  }
}

也可以结合must_not查询不包含某个字段的文档

  • 例子:
#不包含某个字段的文档
GET /bank/_search
{
  "query": {
    "bool": {
      "must_not": [
        {
          "exists": {
            "field": "age"
          }
        }
      ]
    }
  }
}
  1. Prefix Query

    前缀查询,表示查询某个字段且前缀匹配的文档。
  • 例子:
# prefix  query
# 表示email字段中前缀为foster的文档
GET /bank/_search
{
  "query": {
    "prefix": {
      "email.keyword": {
        "value": "foster"
      }
    }
  }
}
  1. Wildcard Query:通配符查询
  • 例子:
# wildcard query 通配符查询
# ? 代表单个字符 
# * 0或多个字符
GET /bank/_search
{
  "query": {
    "wildcard": {
      "email.keyword": {
        "value": "*ware*"
      }
    }
  }
}
  1. Regexp Query
    image.png
  • 例子:
#regexp query
GET /_search
{
    "query": {
        "regexp": {
            "user": {
                "value": "k.*y",
                "flags" : "ALL",
                "max_determinized_states": 10000,
                "rewrite": "constant_score"
            }
        }
    }
}

1.5 Compound queries

compound queries会包裹其他compound queries或leaf queries,合并它们的查询结果及相关性得分,改变他们的行为。

  1. Constant Score Query
    这个查询不会提供匹配得分,但是会根据提供的boost返回相应的值。
  • 例子:
# constant_score
GET /bank/_search
{
  "query": {
    "constant_score": {
      "filter": {
        "term": {
          "age": 24
        }
      },
      "boost": 1.2
    }
  }
}
  1. Bool Query



  • 例子:
# 找到岁数不小于40岁的人
GET /bank/_search
{
  "query": {
    "bool": {
      "must_not": [
        {
          "range": {
            "age": {
              "lt": 40
            }
          }
        }
      ]
    }
  }
}

如果觉得有收获就点个赞吧,更多知识,请点击关注查看我的主页信息哦~

相关文章

网友评论

      本文标题:ES 查询语法解析之Query DSL — 文章很长,慎入

      本文链接:https://www.haomeiwen.com/subject/nyjxxdtx.html