【Elasticsearch】学好Elasticsearch系列-Query DSL 2

本文涉及的产品
检索分析服务 Elasticsearch 版,2核4GB开发者规格 1个月
简介: 【Elasticsearch】学好Elasticsearch系列-Query DSL

Query String

Query String Query是Elasticsearch中的一种查询方式,它允许你使用特定的搜索语法来进行复杂的、灵活的查询。

Query String Query是基于Lucene Query Parser解析器的,因此支持丰富的搜索语法,包括但不限于:

  • 基本文本查询: "quick brown fox"
  • 逻辑操作符 (AND, OR, NOT): "quick AND brown"
  • 范围查询: "age:[18 TO 30]"
  • 通配符查询: "qu?ck br*wn"
  • 分组: "(quick OR brown) AND fox"
  • 字段指定查询: "title:quick"

下面是几个例子:

查询所有

GET /product/_search

分页

GET /product/_search?from=0&size=2&sort=price:asc

精准匹配 exact value

GET /product/_search?q=date:2021-06-01

_all搜索 相当于在所有有索引的字段中检索

all搜索与精准匹配就是带不带字段参数的区别,如果把index索引禁用,则all搜索不会去该字段上查询。

GET /product/_search?q=2021-06-01

精准查询-Term query

精确查询用于查找包含指定精确值的文档,而不是执行全文搜索。

term:匹配和搜索词项完全相等的结果

举个例子:

GET /_search
{
  "query": {
    "term": {
      "user": "kimchy"
    }
  }
}

这个查询会找到"user"字段精确匹配"kimchy"的所有文档。

需要注意的是,term 查询对大小写敏感,并且不会进行分词处理。也就是说,如果你在使用 term 查询时输入了一个完整的句子,它将尝试查找与这个完整句子精确匹配的文档,而不是把句子拆分成单词进行匹配。

term和match_phrase的区别

term 查询和 match_phrase 查询是 Elasticsearch 提供的两种查询方式,它们都用于查找文档,但主要的区别在于如何解析查询字符串以及匹配的精确度。

  1. term 查询:这种查询对待查询字符串为一个完整的单位,不进行分词处理,并且大小写敏感。它可以在文本、数值或布尔类型字段上使用,通常用于精确匹配某个字段的确切值。
  2. match_phrase 查询:这种查询把查询字符串当作一种短语来匹配。查询字符串会被分词器拆分成单独的词项,然后按照词项在查询字符串中的顺序去匹配文档。只有当文档中的词项顺序与查询字符串中的顺序完全一致时才能匹配成功,match_phrase 查询通常对大小写不敏感,除非你的字段映射或索引设置更改了这个行为。

简单来说,term 查询更多的是做精确的、字面的匹配,而 match_phrase 则是做短语匹配,在搜索结果的精确度上,term 查询比 match_phrase 更高。

terms:匹配和搜索词项列表中任意项匹配的结果

terms 查询用于匹配指定字段中包含一个或多个值的文档。这是一个精确匹配查询,不会像全文查询那样对查询字符串进行分析。

假设你有一个 "user" 的字段,并且你想找到该字段值为 "John" 或者 "Jane" 的所有文档,你可以使用 terms 查询:

GET /_search
{
  "query": {
    "terms" : {
      "user" : ["John", "Jane"],
      "boost" : 1.0
    }
  }
}

上面的查询将返回所有"user" 字段等于 "John" 或者 "Jane" 的文档。

其中boost 参数用于增加或减少特定查询的相对权重。它将改变查询结果的相关性分数(_score),以影响最终结果的排名。

例如,在上述 terms 查询中,boost 参数被设置为 1.0。这意味着如果字段 "user" 的值包含 "John" 或 "Jane",那么其相关性分数(_score)就会乘以 1.0。因此,这个设置实际上并没有改变任何东西,因为乘以 1 不会改变原始分数。但是,如果你将 boost 参数设置为大于 1 的数,那么匹配的文档的 _score 将会提高,反之则会降低。

range:范围查找

range 查询允许你查找位于特定范围内的值。这对于日期、数字或其他可排序类型的字段非常有用。

下面的语句会查询出age字段大于等于10,小于等于20的文档。

例子1:假设你有一些表示博客文章的文档,每个文档都有一个发表日期,并且你想找出在特定日期范围内发布的所有文章,你可以使用 range 查询来实现这一目标

GET /_search
{
  "query": {
    "range" : {
      "date" : {
        "gte" : "2020-01-01",
        "lte" : "2020-12-31",
        "format": "yyyy-MM-dd"
      }
    }
  }
}

在上面的查询中,range 查询被用来查找字段 "date" 的值在 "2020-01-01" 和 "2020-12-31"(包含)之间的所有文档。

range 查询支持以下运算符:

  • gt:大于 (greater than)
  • gte:大于等于 (greater than or equal to)
  • lt:小于 (less than)
  • lte:小于等于 (less than or equal to)

例子2:下面的语句会查询出date字段1天前的文档,其中now表示当前时间。

GET product/_search
{
  "query": {
    "range": {
      "date": {
        "gte": "now-1d/d",
        "lt": "now/d"
      }
    }
  }
}

例子3:下面的语句会查询出date字段小于当前时间,大于2021-04-15T08:00:00的文档。time_zone表示时区,意思就是原文档中的数据会被+8小时再去搜索,例如原文档有条数据是:2021-04-15。则该数据能被查询出来。

GET product/_search
{
  "query": {
    "range": {
      "date": {
        "time_zone": "+08:00",
        "gte": "2021-04-15T08:00:00",
        "lt": "now"
      }
    }
  }
}

过滤器-Filter

过滤器(Filter)是一种特殊类型的查询,它不关心评分 (_score),只关心是否匹配。基于这个原因,过滤器比标准的全文查询更快并且能被缓存。

一个典型的使用场景是布尔查询 (bool), 它有两个重要的部分:mustfiltermust 部分用于全文搜索,filter 部分用于过滤结果。看一个例子:

GET /_search
{
  "query": {
    "bool": {
      "must": [
        { "match": { "title": "quick" }}
      ],
      "filter": [
        { "term":  { "published": true }}
      ]
    }
  }
}

在这个查询中,bool 查询包含了一个 must 子句和一个 filter 子句。must 子句会执行全文搜索并对结果进行评分。在这个例子中,它会找出所有标题包含"quick"的文章。

filter 子句则会在 must 子句的基础上进一步过滤结果。在这个例子中,它会筛选出那些已经发布的文章。这个过滤操作不会影响到评分,因为它只关心是否匹配。

总的来说,过滤器非常适合用于分类、范围查询或者确认某个字段是否存在等场景。过滤器的效率高并且可以被缓存,所以在大型数据集上性能表现良好。

Filter缓存机制

在 Elasticsearch 中,过滤查询结果的缓存机制是非常重要的一个性能优化手段。由于过滤器(filter)只关心是否匹配,而不关心评分 (_score),因此它们的结果可以被缓存以提高性能。

每次 filter 查询执行时,Elasticsearch 都会生成一个名为 "bitset" 的数据结构,其中每个文档都对应一个位(0 或 1),表示这个文档是否与 filter 匹配。这个 bitset 就是被存储在缓存中的部分。

如果相同的 filter 查询再次执行,Elasticsearch 可以直接从缓存中获取这个 bitset,而不需要再次遍历所有的文档来找出哪些文档符合这个 filter。这大大提高了查询速度,并减少了 CPU 使用。

这种缓存策略特别适合那些重复查询的场景,例如用户界面的过滤器和类似的功能,因为他们通常会产生很多相同的 filter 查询。

然而,值得注意的是,虽然这种缓存可以显著改善查询性能,但也会占用内存空间。如果你有很多唯一的过滤条件,那么过滤器缓存可能会变得很大,从而导致内存问题。这就需要你对使用的过滤器进行适当的管理和限制。

另外,Elasticsearch 默认情况下会自动选择哪些过滤器进行缓存,考虑到查询频率和成本等因素。你也可以手动配置某个特定的 filter 是否需要进行缓存。

组合查询-Bool query

组合查询可以组合多个查询条件,bool查询也是采用more_matches_is_better的机制,因此满足must和should子句的文档将会合并起来计算分值。

boot和minumum_should_match是参数,其他四个都是查询子句。

  • must:必须满足子句(查询)必须出现在匹配的文档中,并将有助于得分。
  • filter:过滤器不计算相关度分数。
  • should:满足 or子句(查询)应出现在匹配的文档中。
  • must_not:必须不满足,不计算相关度分数 ,not子句(查询)不得出现在匹配的文档中。子句在过滤器上下文中执行,这意味着计分被忽略,并且子句被视为用于缓存。

例子1:下面的语句表示:包含"xiaomi"或"phone" 并且包含"shouji"的文档例子:

GET product/_search
{
    "query": {
        "bool": {
            "must": [
                {
                    "match": {
                        "name": "xiaomi phone"
                    }
                },
                {
                    "match_phrase": {
                        "desc": "shouji"
                    }
                }
            ]
        }
    }
}

should与must或filter一起使用

should 子句与 mustfilter 子句一起使用时,这时候需要注意了!只要满足了 mustfilter 的条件,should 子句就不再是必须的。换句话说,如果存在一个或者多个 mustfilter 子句,那么 should 子句的条件会被视为可选。

然而,如果 should 子句与 must_not 子句单独使用(也就是没有 mustfilter),则至少需要满足一个 should 子句的条件。

这里有一个例子来说明:

GET /_search
{
  "query": {
    "bool": {
      "must": [
        { "term": { "user": "kimchy" }}
      ],
      "filter": [
        { "term":  { "tag": "tech" }}
      ],
      "should": [
        { "term": { "tag": "wow" }},
        { "term": { "tag": "elasticsearch" }}
      ]
    }
  }
}

在这个查询中,mustfilter 子句的条件是必须满足的,而 should 子句的条件则是可选的。如果匹配的文档同时满足 should 子句的条件,那么它们的得分将会更高。

那如果我们一起使用的时候想让should满足该怎么办?这时候minimum_should_match 参数就派上用场了。

minimum_should_match

minimum_should_match参数定义了在 should 子句中至少需要满足多少条件。

例如,如果你有5个 should 子句并且设置了 "minimum_should_match": 3,那么任何匹配至少三个 should 子句的文档都会被返回。

这个参数可以接收绝对数值(如 2)、百分比(如 30%)、和组合(如 3<90% 表示至少匹配3个或者90%,取其中较大的那个)等不同类型的值。

注意:如果 bool 查询中只有 should 子句(没有 mustfilter),那么默认情况下至少需要匹配一个 should 条件,也就是minimum_should_match默认值是1,除非 minimum_should_match 明确设定为其他值。如果包含 mustfilter的情况下minimum_should_match默认值 0。

所以我们可以在包含mustfilter的情况下,设置minimum_should_match值来满足should子句中的条件。


本篇文章就到这里,感谢阅读,如果本篇博客有任何错误和建议,欢迎给我留言指正。

有收获?希望老铁来个三连,给更多的同学看到这篇文章,顺便激励下我,嘻嘻。

相关实践学习
使用阿里云Elasticsearch体验信息检索加速
通过创建登录阿里云Elasticsearch集群,使用DataWorks将MySQL数据同步至Elasticsearch,体验多条件检索效果,简单展示数据同步和信息检索加速的过程和操作。
ElasticSearch 入门精讲
ElasticSearch是一个开源的、基于Lucene的、分布式、高扩展、高实时的搜索与数据分析引擎。根据DB-Engines的排名显示,Elasticsearch是最受欢迎的企业搜索引擎,其次是Apache Solr(也是基于Lucene)。 ElasticSearch的实现原理主要分为以下几个步骤: 用户将数据提交到Elastic Search 数据库中 通过分词控制器去将对应的语句分词,将其权重和分词结果一并存入数据 当用户搜索数据时候,再根据权重将结果排名、打分 将返回结果呈现给用户 Elasticsearch可以用于搜索各种文档。它提供可扩展的搜索,具有接近实时的搜索,并支持多租户。
目录
相关文章
|
Web App开发 自然语言处理 API
巧记Elasticsearch常用DSL语法
记知识先记轮廓,关于DSL语法的轮廓,记住以下3句话即可:1.索引、文档和查询。2.Match、Term和Bool。3.还有翻页和聚合
巧记Elasticsearch常用DSL语法
|
3月前
|
JSON 自然语言处理 算法
ElasticSearch基础2——DSL查询文档,黑马旅游项目查询功能
DSL查询文档、RestClient查询文档、全文检索查询、精准查询、复合查询、地理坐标查询、分页、排序、高亮、黑马旅游案例
ElasticSearch基础2——DSL查询文档,黑马旅游项目查询功能
|
5月前
|
存储 数据库 索引
面试题ES问题之动态映射的定义如何解决
面试题ES问题之动态映射的定义如何解决
42 1
|
7月前
|
SQL Java 关系型数据库
spring data elasticsearch 打印sql(DSL)语句
spring data elasticsearch 打印sql(DSL)语句
475 0
|
JSON 自然语言处理 数据格式
分布式系列教程(33) -ElasticSearch DSL语言查询与过滤
分布式系列教程(33) -ElasticSearch DSL语言查询与过滤
201 0
|
存储 JSON 物联网
【Elasticsearch】学好Elasticsearch系列-Query DSL 1
【Elasticsearch】学好Elasticsearch系列-Query DSL
117 0
|
7月前
|
自然语言处理 索引
Elasticsearch之常用DSL语句
mapping是对索引库中文档的约束
141 1
|
7月前
|
JSON 自然语言处理 算法
【Elasticsearch】DSL查询文档
【Elasticsearch】DSL查询文档
415 0
|
7月前
|
Java 索引
ElasticSearch DSL操作
ElasticSearch DSL操作
116 1
|
7月前
dsl语句查询elasticsearch集群节点分布和资源使用情况
dsl语句查询elasticsearch集群节点分布和资源使用情况
159 0