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" } } ] } }