Elasticsearch Query DSL备忘(Constant score query和Bool Query)

Posted asker009

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Elasticsearch Query DSL备忘(Constant score query和Bool Query)相关的知识,希望对你有一定的参考价值。

Query DSL (Domain Specific Language),基于json的查询方式

1、Constant score query,常量分值查询,目的就是返回指定的score,一般都结合filter使用,因为filter context忽略score。

GET /customer/_search
{
  "query": {
    "constant_score": {
      "filter": {
        "match": {
          "addr": "天津,北京"
        }
      },
      "boost": 5.2
    }
  }
}

result:返回结果中score都是被指定的5.2
{
  "took" : 8,
  "timed_out" : false,
  "_shards" : {
    "total" : 1,
    "successful" : 1,
    "skipped" : 0,
    "failed" : 0
  },
  "hits" : {
    "total" : 2,
    "max_score" : 5.2,
    "hits" : [
      {
        "_index" : "customer",
        "_type" : "doc",
        "_id" : "510221197801023611",
        "_score" : 5.2,
        "_source" : {
          "name" : "王刚",
          "id" : "510221197801023611",
          "addr" : "北京市朝阳区未名路109号",
          "tel" : "13901004491"
        }
      },
      {
        "_index" : "customer",
        "_type" : "doc",
        "_id" : "51228199001013611",
        "_score" : 5.2,
        "_source" : {
          "name" : "白开心",
          "id" : "51228199001013611",
          "addr" : "天津市海港路1021号",
          "tel" : "13590850990"
        }
      }
    ]
  }
}

2、bool query,布尔查询

Bool查询对应Lucene中的BooleanQuery,它由一个或者多个子句组成,每个子句都有特定的类型。

  • must  返回的文档必须满足must子句的条件,并且参与计算分值
  • filter  返回的文档必须满足filter子句的条件。但是不会像must一样参与计算分值
  • should 返回的文档可能满足should子句的条件。bool查询在query context中,并且有一个must或filter子句,即使没有一个should查询匹配,文档也会进行bool匹配。在这种情况下,这些should仅用于影响分数。如果在filter context中,或者没有must或filter子句,那么should子句必须和文档匹配,才能匹配bool查询。这种行为由minimum_should_match 参与决定。
  • must_not 返回的文档必须不满足must_not定义的条件。

官网的例子:

POST _search
{
  "query": {
    "bool" : {
      "must" : {
        "term" : { "user" : "kimchy" }
      },
      "filter": {
        "term" : { "tag" : "tech" }
      },
      "must_not" : {
        "range" : {
          "age" : { "gte" : 10, "lte" : 20 }
        }
      },
      "should" : [
        { "term" : { "tag" : "wow" } },
        { "term" : { "tag" : "elasticsearch" } }
      ],
      "minimum_should_match" : 1,
      "boost" : 1.0
    }
  }
}

bool查询案例分解:

第一步:查询name为“李云龙”的文档

GET /customer/_search
{
  "query": {
    "bool": {
      "must": {
        "term":{"name.keyword":"李云龙"}
      }
    }
  }
}
返回三个文档:
{
  "took" : 0,
  "timed_out" : false,
  "_shards" : {
    "total" : 1,
    "successful" : 1,
    "skipped" : 0,
    "failed" : 0
  },
  "hits" : {
    "total" : 3,
    "max_score" : 1.4916549,
    "hits" : [
      {
        "_index" : "customer",
        "_type" : "doc",
        "_id" : "4",
        "_score" : 1.4916549,
        "_source" : {
          "name" : "李云龙",
          "id" : "510221197001013611",
          "addr" : "昆明市滇池路阳光时代1栋1单元",
          "tel" : "13808712808"
        }
      },
      {
        "_index" : "customer",
        "_type" : "doc",
        "_id" : "224",
        "_score" : 1.4916549,
        "_source" : {
          "name" : "李云龙",
          "id" : "224",
          "addr" : "天津市阳光路2008号",
          "tel" : "13908712808"
        }
      },
      {
        "_index" : "customer",
        "_type" : "doc",
        "_id" : "510221197001013611",
        "_score" : 1.4916549,
        "_source" : {
          "name" : "李云龙",
          "id" : "510221197001013611",
          "addr" : "上海市浦东区华北路8号",
          "tel" : "13908712808"
        }
      }
    ]
  }
}

第二步:加入过滤条件,只保留id为510221197001013611的文档

GET /customer/_search
{
  "query": {
    "bool": {
      "must": {
        "term":{"name.keyword":"李云龙"}
      },
      "filter": {
        "term": {
          "id": "510221197001013611"
        }
      }
    }
  }
}

返回结果减少到2个文档,并且score相同:
{
  "took" : 0,
  "timed_out" : false,
  "_shards" : {
    "total" : 1,
    "successful" : 1,
    "skipped" : 0,
    "failed" : 0
  },
  "hits" : {
    "total" : 2,
    "max_score" : 1.4916549,
    "hits" : [
      {
        "_index" : "customer",
        "_type" : "doc",
        "_id" : "4",
        "_score" : 1.4916549,
        "_source" : {
          "name" : "李云龙",
          "id" : "510221197001013611",
          "addr" : "昆明市滇池路阳光时代1栋1单元",
          "tel" : "13808712808"
        }
      },
      {
        "_index" : "customer",
        "_type" : "doc",
        "_id" : "510221197001013611",
        "_score" : 1.4916549,
        "_source" : {
          "name" : "李云龙",
          "id" : "510221197001013611",
          "addr" : "上海市浦东区华北路8号",
          "tel" : "13908712808"
        }
      }
    ]
  }
}

第三步:使用should,判断addr中必须有昆明市,这种情况下should子句会影响计分

GET /customer/_search
{
  "query": {
    "bool": {
      "must": {
        "term":{"name.keyword":"李云龙"}
      },
      "filter": {
        "term": {
          "id": "510221197001013611"
        }
      },
      "should": [
        {"match": {
          "addr": "昆明市"
        }}
      ]
    }
  }
}
返回结果中,地址是昆明市的文档score加重
{
  "took" : 1,
  "timed_out" : false,
  "_shards" : {
    "total" : 1,
    "successful" : 1,
    "skipped" : 0,
    "failed" : 0
  },
  "hits" : {
    "total" : 2,
    "max_score" : 3.408528,
    "hits" : [
      {
        "_index" : "customer",
        "_type" : "doc",
        "_id" : "4",
        "_score" : 3.408528,
        "_source" : {
          "name" : "李云龙",
          "id" : "510221197001013611",
          "addr" : "昆明市滇池路阳光时代1栋1单元",
          "tel" : "13808712808"
        }
      },
      {
        "_index" : "customer",
        "_type" : "doc",
        "_id" : "510221197001013611",
        "_score" : 1.5720221,
        "_source" : {
          "name" : "李云龙",
          "id" : "510221197001013611",
          "addr" : "上海市浦东区华北路8号",
          "tel" : "13908712808"
        }
      }
    ]
  }
}

第四步:加入must_not排除上海

GET /customer/_search
{
  "query": {
    "bool": {
      "must": {
        "term":{"name.keyword":"李云龙"}
      },
      "filter": {
        "term": {
          "id": "510221197001013611"
        }
      },
      "should": [
        {"match": {
          "addr": "昆明市"
        }}
      ],
      "must_not": [
        {"match": {
          "addr": "上海"
        }}
      ]
    }
  }
}

只返回一个文档:
{
  "took" : 2,
  "timed_out" : false,
  "_shards" : {
    "total" : 1,
    "successful" : 1,
    "skipped" : 0,
    "failed" : 0
  },
  "hits" : {
    "total" : 1,
    "max_score" : 3.408528,
    "hits" : [
      {
        "_index" : "customer",
        "_type" : "doc",
        "_id" : "4",
        "_score" : 3.408528,
        "_source" : {
          "name" : "李云龙",
          "id" : "510221197001013611",
          "addr" : "昆明市滇池路阳光时代1栋1单元",
          "tel" : "13808712808"
        }
      }
    ]
  }
}

 

以上是关于Elasticsearch Query DSL备忘(Constant score query和Bool Query)的主要内容,如果未能解决你的问题,请参考以下文章

Elasticsearch-Query DSL

ES(elasticsearch) query DSL 查询语法

elasticSearch-DSL

elasticsearch query dsl

Elasticsearch Query DSL概述与查询过滤上下文

Elasticsearch的javaAPI之query dsl-queries