1. 程式人生 > >Elasticsearch Query DSL備忘(1)(Constant score query和Bool Query)

Elasticsearch Query DSL備忘(1)(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"
        }
      }
    ]
  }
}