Skip to main content
 首页 » 编程设计

详解Elasticsearch Query DSL

2022年07月19日199dyllove98

详解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的核心思维是全局检索文档及过滤文档。本文分别介绍了不同类型的语法结构并通过示例进行说明,希望对你有帮助。


本文参考链接:https://blog.csdn.net/neweastsun/article/details/104318572
阅读延展