Elasticsearch DSL 查询详解

在 Elasticsearch 中,提供了功能十分丰富、多种表现形式的查询语言—— DSL 查询

DSL 查询使用 JSON 格式的请求体与 Elasticsearch 交互,可以实现各种各样的查询需求。

DSL 查询主要包含两种类型的查询语句:

  • 叶子查询语句 : 用于查询特殊字段的特殊值,例如:match, term, range 等。
  • 复合查询语句 : 可以合并其他的叶子查询或复合查询,从而实现非常复杂的查询逻辑。

查询语句的执行结果依赖于它们是用于查询语境还是过滤语境。

基本语法

使用 DSL 查询,需用到 query 参数。

基本的语法格式:

GET /_search
{
    "query": <query clause>
}

空查询

没有查询条件的查询,就是空查询。它会匹配所有的文档。

GET /_search
{
    "query": {}
}

等同于

GET /_search

等同于

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

基本查询

例如,使用 match 查询 full_name 字段中包含 john 的记录。

GET /_search
{
    "query": {
        "match": {
            "full_name": "john"
        }
    }
}

查询与过滤

DSL 查询根据使用目的的不同分为两种类型:

  • 上下文查询(Query context),简称查询
  • 上下文过滤(Filter context),简称过滤

查询(Query)

在上下文查询语境中,查询语句会询问文档与查询语句的匹配程度,此外,它会判断文档是否匹配并计算相关性评分(_score)的值。

过滤(Filter)

在上下文过滤语境中,查询语句主要解决文档是否匹配的问题,而不会在意匹配程度(相关性评分)。过滤主要用于结构化的数据。

例如:

status 字段的值是否为某个枚举值或布尔值?

age 字段的值是否在 20-35 范围内?

date 字段的值是否在 2016-2019 之间?

一般来说,过滤语句比查询语句的执行效率更高,因为它不用计算文档的相关性评分(score)。

使用频繁的过滤语句的结果集会被 Elasticsearch 自动缓存,以提高性能。

过滤的目的就是粗暴地快速缩小匹配的结果集。

通常,全文搜索或需要用到相关性评分(score)的场景采用查询(query),其他的全部用过滤(filter)。

在进行搜索时,我们常常会在查询语句中,结合查询和过滤来达到我们的查询目的。

下面是一个示例:

GET /_search
{
  "query": { 
    "bool": { 
      "must": [
        { "match": { "title":   "Search"        }}, 
        { "match": { "content": "Elasticsearch" }}  
      ],
      "filter": [ 
        { "term":  { "status": "published" }}, 
        { "range": { "publish_date": { "gte": "2015-01-01" }}} 
      ]
    }
  }
}

全文查询

全文查询语句通常用于全文本字段的查询。

match

match 查询可操作文本、数值和日期类型的数据,分析它们并构建查询语句。

示例:查询 full_name 字段中包含 John 或 Smith 的文档。

GET /_search
{
    "query" : {
        "match" : {
            "full_name" : "John Smith"
        }
    }
}

说明: Elasticsearch 会先使用分析器分析 "John Smith" 为两个独立的项 "John" 和 "Smith",然后再去构建查询。

这里的 full_name 字段可以替换为任何你想查询的字段甚至是 _all 字段。

match 属于 boolean 的类型,也就是说,分析器会对提供的查询文本进行分析并构建 boolean 查询语句。

由 match 构建的 boolean 查询语句默认是逻辑或(or),当然,我们可以通过 operator 参数来改变这个默认行为。

示例:查询 full_name 字段中包含 John 和 Smith 的文档。

GET /_search
{
    "query": {
        "match" : {
            "full_name" : {
                "query" : "John Smith",
                "operator" : "and"
            }
        }
    }
}

说明: full_name 是字段名称,query 参数的值是提供的查询文本,operator 参数用于设置 match 的逻辑(or 还是 and)。

match_phrase

match_phrase,即短语(词组)匹配,它会分析提供的查询文本并构建一个 phrase 查询。

match_phrase 用于精准的 phase 匹配。

示例:查询 full_name 字段中包含 "John Smith" 短语的文档。

GET /_search
{
    "query" : {
        "match_phrase" : {
            "full_name" : "John Smith"
        }
    }
}

我们也可以给提供的查询文本指定 analyzer(分析器),如果没有指定,默认使用字段的显式 mapping 中的定义,或者默认的 search analyzer。

GET /_search
{
    "query": {
        "match_phrase" : {
            "full_name" : {
                "query" : "John Smith",
                "analyzer" : "standard"
            }
        }
    }
}

match_phrase_prefix

match_phrase_prefix 和 match_phrase 类似,但 match_phrase_prefix 不是精准匹配,而是前缀匹配,它会对查询文本的最后一个字符后的内容进行通配符搜索。

示例:查询 full_name 字段中以 "John Smi" 短语开头的文档。

GET /_search
{
    "query" : {
        "match_phrase_prefix" : {
            "full_name" : "John Smi"
        }
    }
}

multi_match

multi_match 用于多字段匹配查询。

GET /_search
{
    "query" : {
        "multi_match": {
          "query": "John Smith",
          "fields": ["first_name", "full_name"]
        }
    }
}

Term-level 查询

我们知道,全文查询在执行查询之前,会先对提供的查询文本进行分析。

然而,Term-level 查询是直接查询倒排索引中的确切的值。

Term-level 查询通常用于结构化的数据,如数值、日期、枚举值或关键字,而不是文本(text)。

term

term 用于查询指定字段的倒排索引包含某个确切值的记录。

POST /_search
{
  "query": {
    "term" : { "first_name" : "john" } 
  }
}

terms

terms 和 term 类似,只不过提供的确切的值是数组。类似于 MySQL 的 in 条件。

POST /_search
{
  "query": {
    "terms" : { "full_name" : ["john", "john2"] } 
  }
}
POST /_search
{
  "query": {
    "constant_score": {
      "filter": { "terms" : { "full_name" : ["john", "john2"] }}
    }
  }
}

range

range 用于范围查询。

GET /_search
{
    "query": {
        "range" : {
            "info.age" : {
                "gte" : 28,
                "lt" : 60,
                "boost" : 2.0
            }
        }
    }
}

说明: boost 参数可用于调整相关性评分(score)的值。

GET /_search
{
    "query": {
        "range" : {
            "date" : {
                "gt" : "now-3d/d",
                "lt" :  "now"
            }
        }
    }
}

exists

exists 返回字段值不为 null 的记录。

GET /_search
{
    "query": {
        "exists" : { "field" : "user" }
    }
}

prefix

prefix 返回字段的 term 以确切的前缀(前缀不会被分析)开头的记录。

GET /_search
{
    "query": {
        "prefix" : { "full_name" : "joh" }
    }
}

wildcard

wildcard 指的是通配符查询。

支持的通配符主要有:

  • * 匹配 0 个或多个任意字符
  • ? 匹配 1 个任意字符
GET /_search
{
    "query": {
        "wildcard" : { "full_name" : "john*" }
    }
}

regexp

regexp 指的是正则查询。

GET /_search
{
    "query": {
        "regexp" : { "full_name" : "jo.*" }
    }
}

fuzzy

fuzzy 指的是容差查询,即可以容忍确切的值和倒排索引中的 term 之间有误差。

GET /_search
{
    "query": {
        "fuzzy" : { "full_name" : "joh" }
    }
}
GET /_search
{
    "query": {
        "fuzzy" : {
            "full_name" : {
                "value" :         "joh",
                "fuzziness" :     2,
                "prefix_length" : 0,
                "max_expansions": 100
            }
        }
    }
}

type

type 查询指的是根据文档的 type 来查询。

这里的 type 就是文档的类别(逻辑分组),类似于 MySQL 的数据表。

GET /_search
{
    "query": {
        "type" : {
            "value" : "user"
        }
    }
}

ids

ids 查询指的是根据文档的 id 来查询。

GET _search
{
    "query": {
        "ids" : { "values" : ["1", "2", "60"] }
    }
}

复合查询

constant_score

constant_score 复合查询只会在过滤上下文中执行查询语句,并且返回的所有的记录的 _score 值是一个常量。

GET /_search
{
    "query": {
        "constant_score" : {
            "filter" : {
                "term" : { "full_name" : "john"}
            },
            "boost" : 1.5
        }
    }
}

bool

bool 复合查询用于组合叶子查询语句或复合查询语句。如:must, should, must_not, or filter。

  • must 必须匹配。
  • should 至少匹配一个文档。
  • filter 必须匹配,忽略相关性评分。
  • must_not 必须不匹配,忽略相关性评分。

说明: must 和 should 在查询上下文中执行;must_not 和 filter 在过滤上下文中执行。

POST /_search
{
    "query": {
        "bool" : {
            "must" : {
              "term" : { "last_name" : "smith" }
            },
            "filter": {
              "term" : { "info.interests" : "musics" }
            },
            "must_not" : {
              "range" : {
                "info.age" : { "gte" : 10, "lte" : 25 }
              }
            },
            "should" : [
              { "term" : { "full_name" : "john" } },
              { "term" : { "full_name" : "smith" } }
            ],
            "minimum_should_match" : 1,
            "boost" : 2.0
        }
    }
}

参考文献

[1] https://www.elastic.co/guide/en/elasticsearch/reference/5.2/index.html

发布了378 篇原创文章 · 获赞 589 · 访问量 108万+

猜你喜欢

转载自blog.csdn.net/lamp_yang_3533/article/details/97618687
今日推荐