elk笔记13--Queries-compound queries

1 compound 查询简介

复合查询包裹着其它复合查询或叶子查询,它要么结合其它查询的结果和相关度分数,以改变它们的行为,要么从查询上下文切换到过滤上下文。

该范畴内的查询包括 bool查询、boosting查询、constant_score查询、dis_max 查询、function_score查询 等5大类。

2 compound 查询分类

2.1 bool query

该查询返回能匹配boolean组合的其它请求,该查询对应Lucene 的 BooleanQuery。bool查询中可以使用一个或者多个boolean类型的子句,每个子句使用must、filter、should、must_not 之一的查询事件做为标记。
must 即为与,文档匹配到must的条件后,会对其最终分数作出一定贡献;
filter 也是与,与must不同的是,filter不影响最终分数,如果bool中只有一个filter,则返回的所有文档的分数都为0;
should 代表或,should中如果有多个匹配子句,匹配任何一个子句就会命中文档;
must_not 代表非,即匹配到must_not的文档不会被返回,它和filter一样不影响最终分数,如果bool中只有一个must_not,则返回的所有文档的分数都为0.

查询用户为adb或者mary,且单次购物金额大于100的购物记录
GET kibana_sample_data_ecommerce/_search
{
"query": {
"bool": {
"should": [
{
"term": {
"user": {
"value": "abd"
}
}
},
{
"term": {
"user": {
"value": "mary"
}
}
}
],
"must_not": [
{
"range": {
"taxful_total_price": {
"lte": 100
}
}
}
]
}
}
}

2.2 boosting query

boosting查询返回匹配为积极查询的文档,同时减少匹配到为消极查询的文档相关度分数。其中,positive、negative和negative_boost 为boosting的顶层参数,必不可少;negative_boost 的值为0-1之间的浮点数字。

若一个匹配返回的文档既满足positive查询子句又满足negative查询子句,那么boosting查询计算相似度分数步骤如下:
1)获取从positive查询中的原始分数;
2)将获取的分数与negative_boost系数相乘得到最终分;

查询abd 和mary用户的购物数据,优先返回abd的数据。
GET kibana_sample_data_ecommerce/_search
{
"track_total_hits":true,
"size": 500,
"query": {
"boosting": {
"positive": {
"term": {
"user": {
"value": "mary"
}
}
},
"negative": {
"term": {
"day_of_week_i": {
"value": 2
}
}
},
"negative_boost": 0.2
}
}
}
当前 nvyUM3QBANuM53D3DaOL 记录的 day_of_week_i 为1:
当设置 day_of_week_i 为 1的时候,由于刚好匹配到negative,nvyUM3QBANuM53D3DaOL score 为 0.6824043,
当设置 day_of_week_i 为 2的时候,由于没有匹配到negative,nvyUM3QBANuM53D3DaOL score 为 3.4120214,
由此可见,同时满足positive和negtive的时候,positive的score*negative_boost即为最终的score(会存在一定的四舍五入)。

GET kibana_sample_data_ecommerce/_search
{
"track_total_hits":true,
"size": 500,
"query": {
"boosting": {
"positive": {
"term": {
"user": {
"value": "mary"
}
}
},
"negative": {
"term": {
"user": {
"value": "abd"
}
}
},
"negative_boost": 0.2
}
}
}

day_of_week_i 为1:

elk笔记13--Queries-compound queries_compound query


day_of_week_i 为2:

elk笔记13--Queries-compound queries_es dsl_02

2.3 constant_score query

constant_score 查询包含一个过滤查询,每个匹配的文档都有一个相同的相关度分数,该分数等于boost参数的值。默认情况下boost值为1.0。
顶层参数:filter,boost,其中boost可以省略。

GET kibana_sample_data_ecommerce/_search?size=2
{
"query": {
"constant_score": {
"filter": {
"term": {
"user": "abd"
}
},
"boost": 1.2
}
}
}

2.4 dis_max query

返回的文档匹配一个或者多个包含的查询,被称作查询子句或者子句。如果返回的文档匹配多个查询子句,则最终返回score为max{所有子句的score}+sum{其它子句的score*tie_breaker}。
其实际使用意义在于:搜索到的结果是某个filed中匹配到尽可能多的关键词,该类型文档被排在前面;而不是尽可能多的fields 匹配到了少数关键词排在前面。即单个匹配最佳的做为最好的文档。

顶层参数:queries,tie_breaker,其中tie_breaker为可选参数。

创建索引,设置mappping
PUT test
{
"mappings": {
"properties": {
"aa": {
"type": "text"
},
"bb": {
"type": "text"
},
"cc": {
"type": "text"
},
"dd": {
"type": "text"
}
}
}
}
写入数据
PUT test/_bulk?refresh
{"index":{"_id":1}}
{"aa":"aa"}
{"index":{"_id":2}}
{"aa":"aa","bb":"bb"}
{"index":{"_id":3}}
{"aa":"aa","bb":"bb","cc":"cc"}
{"index":{"_id":4}}
{"aa":"aa","bb":"bb","cc":"cc","dd":"dd"}
测试
GET test/_search
{
"query": {
"dis_max": {
"tie_breaker": 0, # 该值为0-1.0 之间,省略时候默认为0
"queries": [
{"term": {"bb": {"value": "bb"}} },
{"term": {"aa": {"value": "aa"}} }
]
}
}
}

query 中只有一项:

只有一项aa字段的时候,score为0.2876821

elk笔记13--Queries-compound queries_3d_03


tie_breaker 为0:

只有2项aa,bb字段的时候,由于tie_breaker为0,aa和bb是对等的,所以score依然为0.2876821

elk笔记13--Queries-compound queries_es dsl_04


tie_breaker 为0.5:

只有2项aa,bb字段的时候,由于tie_breaker为0.5,aa和bb是对等的,所以score 为max{aa的score,bb的score}+0.5*{aa或bb}之一的score=0.2876821*1.5=0.43152314

elk笔记13--Queries-compound queries_es dsl_05

2.5 function_score query

function_score 允许用户修改每个文档的相关度分数。

function_score 既可以使用一个单一的function,

此处直接在最外层使用单一的 random_score
GET /_search
{
"query": {
"function_score": {
"query": { "match_all": {} },
"boost": "5",
"random_score": {},
"boost_mode":"multiply"
}
}
}

也可以使用多个function,

此处在最外层使用 functions, 内部又使用 random_score 和 weight 2个function
GET /_search
{
"query": {
"function_score": {
"query": { "match_all": {} },
"boost": "5",
"functions": [
{
"filter": { "match": { "test": "bar" } },
"random_score": {},
"weight": 23
},
{
"filter": { "match": { "test": "cat" } },
"weight": 42
}
],
"max_boost": 42,
"score_mode": "max",
"boost_mode": "multiply",
"min_score" : 42
}
}
}

如果function中没有给出任何过滤,则等价于匹配所有文档,即为match_all:{};
最外层参数score_mode,可以使用 multiply,sum,avg,first,max,min;
最外层参数boost_mode, 可以使用 multiply,replace,sum,avg,first,max,min;

function_score 支持多种score 函数, 具体内容见​​query-dsl-function-score-query.html​

  • script_score
  • weight
  • random_score
  • field_value_factor
  • decay functions: gauss, linear, exp

3 说明

  1. 参考文档
    ​​​compound-queries​
  2. 测试环境
    本文测试案例对应的 es 版本为7.2.1
    测试数据为kibana自带数据,Home->Add data->Sample data->Sample eCommerce orders