• Home
  • Articles
    • 日志
    • 妍小言
    • 舒小书
    • 浩然说
    • 生活日记
  • All Tags

Elasticsearch DSL简述

18 Sep 2017

Reading time ~2 minutes

数据准备

POST /my_index/my_type/_bulk
{ "index": { "_id": 1 }}
{ "title": "The quick brown fox" }
{ "index": { "_id": 2 }}
{ "title": "The quick brown fox jumps over the lazy dog" }
{ "index": { "_id": 3 }}
{ "title": "The quick brown fox jumps over the quick dog" }
{ "index": { "_id": 4 }}
{ "title": "Brown fox brown dog" }

开始

GET /my_index/my_type/_search
{
    "query": {
        "match": {
            "title": "QUICK!"
        }
    }
}

Elasticsearch 执行上面这个 match 查询的步骤是:

  1. 检查字段类型 。

标题 title 字段是一个 string 类型( analyzed )已分析的全文字段,这意味着查询字符串本身也应该被分析。

  1. 分析查询字符串 。

将查询的字符串 QUICK! 传入标准分析器中,输出的结果是单个项 quick 。因为只有一个单词项,所以 match 查询执行的是单个底层 term 查询。

  1. 查找匹配文档 。

用 term 查询在倒排索引中查找 quick 然后获取一组包含该项的文档,本例的结果是文档:1、2 和 3 。

  1. 为每个文档评分 。

用 term 查询计算每个文档相关度评分 _score ,这是种将 词频(term frequency,即词 quick 在相关文档的 title 字段中出现的频率)和反向文档频率(inverse document frequency,即词 quick 在所有文档的 title 字段中出现的频率),以及字段的长度(即字段越短相关度越高)相结合的计算方式。参见 相关性的介绍 。

多词查询

GET /my_index/my_type/_search
{
    "query": {
        "match": {
            "title": "BROWN DOG!"
        }
    }
}
  • 如果title 字段是一个 string 类型( analyzed )已分析的全文字段,那么查询字符串也会选择相应的分词器对其进行分词
  • 上例中会将BROWN DOG!分成 brown dog
  • 默认查询词项关系为or的关系,则只要doc中包含其中一个词项,即会返回doc。

修改关系符

GET /my_index/my_type/_search
{
    "query": {
        "match": {
            "title": {      
                "query":    "BROWN DOG!",
                "operator": "and"
            }
        }
    }
}
  • 设置查询词项为and关系。

bool查询


{
   "bool" : {
      "must" :     [],
      "should" :   [],
      "must_not" : [],
   }
}

  • must 所有的语句都 必须(must) 匹配,与 AND 等价。
  • must_not 所有的语句都 不能(must not) 匹配,与 NOT 等价。
  • should 至少有一个语句要匹配,与 OR 等价。

  • demo

{
  "query": {
    "bool": {
      "must":     { "match": { "title": "quick" }},
      "must_not": { "match": { "title": "lazy"  }},
      "should": [
                  { "match": { "title": "brown" }},
                  { "match": { "title": "dog"   }}
      ]
    }
  }
}

精度控制

  • 我们可以通过 minimum_should_match 参数控制需要匹配的语句的数量, 它既可以是一个绝对的数字,又可以是个百分比

GET /my_index/my_type/_search
{
  "query": {
    "bool": {
      "should": [
        { "match": { "title": "brown" }},
        { "match": { "title": "fox"   }},
        { "match": { "title": "dog"   }}
      ],
      "minimum_should_match": 2 
    }
  }
}
  • 这个查询结果会将所有满足以下条件的文档返回: title 字段包含 “brown” AND “fox” 、 “brown” AND “dog” 或 “fox” AND “dog” 。如果有文档包含所有三个条件,它会比只包含两个的文档更相关。

底层查询

  1. 关键字:term,不会对查询字符串进行分析。
  2. 上面的集中查询都是上层查询,会对查询字符串进行分析。
  3. 上层查询会讲查询语句分析之后转成底层查询。

如:

{
    "match": { "title": "brown fox"}
}

{
  "bool": {
    "should": [
      { "term": { "title": "brown" }},
      { "term": { "title": "fox"   }}
    ]
  }
}
{
    "match": {
        "title": {
            "query":    "brown fox",
            "operator": "and"
        }
    }
}

{
  "bool": {
    "must": [
      { "term": { "title": "brown" }},
      { "term": { "title": "fox"   }}
    ]
  }
}

过滤器

  • 当进行精确值查找时, 我们会使用过滤器(filters)。过滤器很重要,因为它们执行速度非常快,不会计算相关度(直接跳过了整个评分阶段)而且很容易被缓存。

GET /my_index/my_type/_search
{
    "query" : {
        "constant_score" : { 
            "filter" : {
                "term" : { 
                    "price" : 20
                }
            }
        }
    }
}

GET /my_store/products/_search
{
   "query" : {
      "filtered" : { 
         "filter" : {
            "bool" : {
              "should" : [
                 { "term" : {"price" : 20}}, 
                 { "term" : {"productID" : "XHDK-A-1293-#fJ3"}} 
              ],
              "must_not" : {
                 "term" : {"price" : 30} 
              }
           }
         }
      }
   }
}

GET /my_store/products/_search
{
    "query" : {
        "constant_score" : {
            "filter" : {
                "range" : {
                    "price" : {
                        "gte" : 20,
                        "lt"  : 40
                    }
                }
            }
        }
    }
}


elasticsearchdsl