Elasticsearch Query DSL 案例解析

Published:

结构化搜索案例

查询价格为20的所有记录

{
    "query" : {
        "constant_score": {
            "filter": {
                "term": {
                    "price" : 20
                }
            }
        }
    }
}

在结构化查询中,我们得到的结果只有结果:。判断是否的过滤查询一般直接使用关键字filter。这里在query关键字中嵌套使用constant_score,从而不需要计算相关度,简化运算成本,可以达到同样效果。

更复杂的嵌套案例

  • 先筛选出发行日期在 2014-01-01 以后,且价格小于等于 29.99 的非 ebooks 类别的所有数据。

  • 在上述结果中去除其 tag 为 spam 且 title 和 how to make millions 无关数据。

  • 对剩余的数据 tag 为 starred 的加分并返回。

{
    "bool": {
        "must": {
            "match": {"title": "how to make millions"}
        },
        "must_not": {
            "match": {"tag": "spam"}
        },
        "should": [
            {
                "match": {"tag": "starred"}
            }
        ],
        "filter":{
            "bool": {
                "must": [
                    {"range": {"date": { "gte": "2014-01-01"}}},
                    {"range": {"price": { "lte": 29.99 }}}
                ],
                "must_not": [
                    {"term": {"category": "ebooks"}}
               ]
            }
        }
    }
}

可以在bool类型查询中内部结合其他 must, must_not, should, match 等关键字,形成嵌套结构。

  • must:满足查询体中的所有条件。

  • must_not:不能满足查询体内的任何条件。

  • should:多个条件中,每满足一个条件,其_score值加分。当存在 must 时,should 中均为满足则不加分;当不存在 must 条件时, should 中均不满足则过滤掉。

  • filter:一系列必须匹配的条件,起第一步过滤作用。

查询失败案例

数据中存在该记录,但查询结果为空

{
    "term": {
        "productID": "XHDK-A-1293-#fJ3"
    }
}

对该查询体解析后得到:

{
  "tokens" : [ {
    "token" :        "xhdk",
    "start_offset" : 0,
    "end_offset" :   4,
    "type" :         "<ALPHANUM>",
    "position" :     1
  }, {
    "token" :        "a",
    "start_offset" : 5,
    "end_offset" :   6,
    "type" :         "<ALPHANUM>",
    "position" :     2
  }, {
    "token" :        "1293",
    "start_offset" : 7,
    "end_offset" :   11,
    "type" :         "<NUM>",
    "position" :     3
  }, {
    "token" :        "fj3",
    "start_offset" : 13,
    "end_offset" :   16,
    "type" :         "<ALPHANUM>",
    "position" :     4
  } ]
}

因此导致查询失败的原因是:

  1. 原来的整体ID被解析成了四个token.
  2. 所有字母转化成了小写。
  3. -# 符号已经丢失。

解决这种问题的唯一方法是将文档的 index 类型更新为 not_analyzed