欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

详解Elasticsearch Query DSL

程序员文章站 2024-02-09 18:06:30
...

详解Elasticsearch Query DSL

Elasticsearch是目前的首选搜索、分析引擎,但要熟练掌握查询DSL着实不易。本文在前文的基础上进一步深入学习。

1. 精确检索 vs 全文检索

Elasticsearch中所有检索主要可分为三类:

  • 精确检索
  • 全文检索
  • 两者组合检索(简称组合检索)

文档字段可分为两类:精确文本(keyword)和分析文本(text,也称为全文本)。精确文本如user_id, date, email_addresses等。分析文本如product_description 、 email_body等。通过这些字段名称可以理解,对应文本内容可以被分析(分词),通常是人类理解的自然语言。

查询文档可以通过精确值进行过滤检索。此时检索条件返回二值(是、否),例如,文档的user_id等于123,创建时间是否在一定日期范围内等。

另一方面,通过分析分别进行文档检索,基于相关性返回检索结果,不再是二值(是、否)。例如,文档的分析文本中包括Hello,Elasticsearch。那么通过该Hello world 或 Elasticsearch tutorial都可以检索到该文本。

从这个角度我们能推断全文检索是非常复杂的操作,依据不同类型文本数据涉及到不同分析包实现。如一些分析包实现是用于特定语言分析,缺省分析包是标准分析器,按照单词进行分词,转成小写并删除标点符号。因为全文检索比精确检索更加复杂,故性能上应该精确检索要更好。有时也称全文检索为分析检索。

2. Query DSL

elasticsearch 查询有一个或多个查询子句构成。查询子句能被组合创建其他查询子句,称为组合查询子句。所有查询子句有下面两者格式:

{
  QUERY_CLAUSE: {
    ARGUMENT: VALUE,
    ARGUMENT: VALUE,...
  }
}

{
  QUERY_CLAUSE: {
    FIELD_NAME: {
      ARGUMENT: VALUE,
      ARGUMENT: VALUE,...
    }
  }
}

语法规则:查询子句可以重复地嵌套在其他查找子句内。

{
  QUERY_CLAUSE {
    QUERY_CLAUSE: {
      QUERY_CLAUSE: {
        QUERY_CLAUSE: {
          ARGUMENT: VALUE,
          ARGUMENT: VALUE,...
        }
      }
    }
  }
}

下面分别对一些主要的查询子句进行说明。

3. 常见查询子句

3.1. Match 查询子句

Match 查询子句是最通用、最常用的查询子句。其非常智能,当运行在分析文本字段时则执行全文检索查询,对精确值字段时则执行过滤查询。

下面示例,第一个查询子句在description字段上执行全文检索,而其他两个字段则针对精确值执行过滤检索。

{ "match": { "description": "Fourier analysis signals processing" }}
{ "match": { "date": "2014-09-01" }}
{ "match": { "visible": true }}

3.2. Match All子句

Match All子句返回所有文档。类似于Sql:SELECT * FROM table

{ "match_all": {} }

3.3. Term/Terms 查询子句

Term/Terms子句各自用于使用单个值或多个值过滤精确值字段。在多值情况下,使用OR进行连接。

举例,第一个子句查询所有tag字段中包括“math”的文档。第二个查询所有文档的tag字段包括 “math” 或 “statistics”。

{ "term": { "tag": "math" }}
{ "terms": { "tag": ["math", "statistics"] }}

3.4. Multi Match子句

Multi Match子句在多个字段上执行匹配查询。

{
  "multi_match": {
    "query": "probability theory",
    "fields": ["title", "body"]
  }
}

3.5. Exists 和 Missing 子句

exists子句检查是否包括特定字段,missing子句检查文档在特定字段上没有值,类似于Sql 的is null 或 is not null 子句。示例如下:

{
  "exists" : {
    "field" : "title"
  }
}
{
  "missing" : {
    "field" : "title"
  }
}

3.6. Range 子句

Range 过滤子句用于过滤数值或日期字段在一定范围内,使用gt gte lt lte四个操作。

{ "range" : { "age" : { "gt" : 30 } } }
{ 
  "range": {
    "born" : {
       "gte": "01/01/2012",
       "lte": "2013",
       "format": "dd/MM/yyyy||yyyy"
    }
  }
}

3.7. Bool 子句

有其他查询子句构建查询子句称为组合查询子句。注意组合查询子句也可以组合其他组合查询子句,允许多层嵌套。

boo查询子句是组合查询子句的一个示例,常用于使用布尔操作组合多个查询子句。有三种支持的操作 must must_not 和 should,分别对应 AND , NOT , 和 OR 。

举例,加入有索引posts,需查询包括 math的且不包括 probability,同时也可以包括 unread 或 favorited。

{
    "bool": {
        "must":     { "term": { "tag":    "math" }},
        "must_not": { "term": { "tag":    "probability"  }},
        "should": [
                    { "term": { "favorite": true   }},
                    { "term": { "unread":  true   }}
        ]
    }
}

3.8. 使用过滤组合全文检索

前面已经分别讨论了精确查询上下文和全文检索上下文,但实际应用中通常需要组合两者。一般使用filter子句进行组合。

下面示例搜索posts索引中的文档,首先body字段中进行全文检索"Probability Theory",然后在增加条件upvotes 大于20 且 tag字段中包括 “frequentist” 关键字进行过滤。

{
  "query": {
    "bool": {
      "must": [
        {"match": { "body": "Probability Theory" }}
      ],
      "filter": {
        "bool": {
          "must": {
            "range":  { "upvotes" : { "gt" : 20 } } 
          },
          "must_not": { "term":  { "tag": "frequentist" } }
        }
      }
    }
  }
}

4. 总结

elasticsearch 的查询DSL的核心思维是全局检索文档及过滤文档。本文分别介绍了不同类型的语法结构并通过示例进行说明,希望对你有帮助。

相关标签: Elasticsearch