elasticsearch version: 7.10.1
dis_max介绍
dis_max查询(disambiguation maximum) 可以指定多个查询,并将每个查询结果的分数进行合并。它通常用于对多个字段执行相同查询的情况。
dis_max的语法
GET /_search
{
"query": {
"dis_max": {
"queries": [
{ "term": { "title": "Quick pets" } },
{ "term": { "body": "Quick pets" } }
],
"tie_breaker": 0.7
}
}
}
关键词 | 语法介绍 |
---|---|
queries | 多个查询对象的数组 |
tie_breaker | 综合查询结果的平滑因子,默认为0 |
查询流程
- 对每个查询分别获取命中的文档和分数
- 对于每个文档获得各个查询的最大分数
- 将上一步的最大分数与tie_breaker相乘后得到平滑后的分数
- 使用平滑后的份额数进行排序输出结果
dis_max的案例
案例背景:
某网上书城,索引中包含了图书的名称、作者、内容简介等字段。当用户搜索一个查询词时,我们希望:
优先返回书名匹配的结果
其次返回作者信息匹配的结果
最后返回简介匹配的结果
索引创建:
PUT books
{
"mappings": {
"properties": {
"name": {
"type": "text"
},
"author": {
"type": "text"
},
"description": {
"type": "text"
}
}
}
}
文档示例:
POST books/_bulk
{"index":{}}
{"name":"红楼梦","author":"曹雪芹", "description":"一部描写封建社会的经典名著,讲述了贾、王两家家族的兴衰历史"}
{"index":{}}
{"name":"西游记","author":"吴承恩","description":"四大名着之一,描写了孙悟空护送唐僧取经的故事"}
{"index":{}}
{"name":"三国演义","author":"罗贯中","description":"反映三国时代的一部长篇小说,描述了魏、蜀、吴三国之间的矛盾和斗争"}
{"index":{}}
{"name":"水浒传","author":"施耐庵","description":"记载宋江领导的起义军和官军之间的斗争"}
{"index":{}}
{"name":"简爱","author":"夏洛蒂·勃朗特","description":"描写了简爱的成长经历和与劳契先生的爱情故事"}
{"index":{}}
{"name":"了不起的盖茨比","author":"F.斯科特·菲茨杰拉德","description":"描写了上流社会虚荣和空虚的代表作"}
{"index":{}}
{"name":"老人与海","author":"海明威","description":"著名小说家海明威的经典代表作之一"}
{"index":{}}
{"name":"悲惨世界","author":"维克多·雨果","description":"法国文豪雨果的代表作之一,描写19世纪初期巴黎的社会问题"}
dis_max查询:
GET books/_search
{
"query": {
"dis_max": {
"queries": [
{"match": {"name": "演义"}},
{"match": {"author": "演义"}},
{"match": {"description": "演义"}}
],
"tie_breaker": 0.2
}
}
}
查询解析:
- 同时匹配name、author和description字段
- tie_breaker设为0.2,即name字段权重为1, author为0.2, description为0.2
- 这样就实现了按字段优先级别进行排序的需求
tie_breaker
取值为0时,代表取所有查询语句中分数最高的那一个作为文档的最终分数。
取值为1时,代表将所有查询语句的分数加权平均作为文档的最终分数。
取值在0到1之间时,会在上述两种方式之间进行插值计算。
具体计算公式如下:
new_score = (max_score_from_subqueries + (sum_of_other_subscores * tie_breaker_value)
- max_score_from_subqueries 最大得分项
- 将任何其他匹配子句的分数乘以该tie_breaker值。
- 将最高分数添加到相乘分数中