详解Elasticsearch Query DSL

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

发布了395 篇原创文章 · 获赞 761 · 访问量 143万+

猜你喜欢

转载自blog.csdn.net/neweastsun/article/details/104318572