Elasticsearch 评分score计算中的Boost 和 queryNorm
本来没有这篇文章,在公司分享ES的时候遇到一个问题,使用boost的时候,怎么从评分score中知道boost的影响。
虽然我们从查询结果可以直观看到,boost起了应有的作用,但是在explain的时候,找了很久也不明白,boost去哪了?
这个问题花了点时间,不过还是挺值得。由于没有直接用过lucene,也从没想过到lucene网站上去看文档。在Elastic的文档中发现这样一段描述
In fact, reading the explain output is a little more complex than that. You won’t see the boost value or t.getBoost() mentioned in the explanation at all. Instead, the boost is rolled into the queryNorm that is applied to a particular term. Although we said that the queryNorm is the same for every term, you will see that the queryNorm for a boosted term is higher than the queryNorm for an unboosted term.
大概是说:从explain中寻找boost是有点复杂的,因为它被放到queryNorm的计算当中了
queryNorm是怎么计算的?
首先我们应该很容易在explain计算idf的部分看到queryNorm。而计算queryNorm的方式是在底部序号为1的lucene的参考资料中。
计算公式如下:

从这里可以看出我们还需要一个公式

有了这两个公式,我们就可以计算queryNorm,而queryNorm中融合了t.getBoost()这就是我们所关心Boost。显然Boost不是简单的乘上了某个倍数,所以我们很难直观的从score中看到,评分被乘了10或者20,也是我们在分享的时候,找了半天,也没有找到一个整数倍数的原因。
在Elasticsearch 中queryNorm是怎么计算的?
虽然我们有了公式,不过利用公式带入到我们的查询参数中会发现,数值还是有点偏差,有一些细节在公式中并没有体现。通过实验(非源码)我大概能了解计算方式,这里我就举一个实际例子来看ES怎么计算queryNorm。
首先设计一条查询语句,这里不讨论idf的计算,设计的查询中idf都是1
{
"size":30,
"query":{
"bool": {
"should": [
{
"match": {
"name": {
"query": "便宜了",
"boost": 1
}
}
},
{
"match": {
"server": {
"query": "电信",
"boost": 1
}
}
}
]
}
}
}
这是一个bool查询,(Lucene (and thus Elasticsearch) uses the Boolean model to find matching documents,我们的很多查询其实都被看做bool查询,ES只是提供了比较友好的其他查询方式,比如terms查询就是一种bool的should查询,或者直观一点,就是or条件查询)。boost都是1,默认的boost也是1。根据公式,我们按照每个字一个词进行分词的情况下,一共搜索了5个字,计算queryNorm的方式如下:
1/Math.sqrt(5) = 0.4472136
符合我们的预期,如果我们修改boost呢?
{
"size":30,
"query":{
"bool": {
"should": [
{
"match": {
"name": {
"query": "便宜了",
"boost": 4
}
}
},
{
"match": {
"server": {
"query": "电信",
"boost": 1
}
}
}
]
}
}
}
按照公式t.getBoost() 在计算“便宜了” 三个字的时候,应该要乘以4,计算公式应该是
1/Math.sqrt((1 * 4)^2 * 3 + 2 * 1) =0.1414213
但实际情况并非如此,其实ES在处理这个时候,如果较大的boost命中,es将小的那个值变成了0.25,也就是4分之一
1/Math.sqrt(3 + 2 * (1 * 0.25)^2) = 0.5656854
反过来如果,较大的boost没有命中,就会放大较大的boost的影响,采用第一个算法取用 0.1414213,所以如果有两个文档分别命中:
- name命中, 无论server是否命中,采用0.5656854
- name无命中, server命中,采用,0.1414213
两个数相除正好是4倍左右,可以看到,如果字数差距再大一些,倍数可能不是4,会有一定偏差
note:以上分析结果基于试验,ES和lucene源码不一定是这样实现,毕竟公式可以各种变化计算来达到4倍差值。
参考资料:
- http://lucene.apache.org/core/4_6_0/core/org/apache/lucene/search/similarities/TFIDFSimilarity.html
- https://www.elastic.co/guide/en/elasticsearch/guide/current/scoring-theory.html#field-norm
Elasticsearch 评分score计算中的Boost 和 queryNorm的更多相关文章
- Elasticsearch学习笔记(十四)relevance score相关性评分的计算(1)
一.多shard场景下relevance score不准确问题 1.问题描述: 多个shard下,如果每个shard包含指定搜索条件的document数量不均匀的情况下, ...
- elasticsearch relevance score相关性评分的计算
一.多shard场景下relevance score不准确问题 1.问题描述: 多个shard下,如果每个shard包含指定搜索条件的document数量不均匀的情况下,会导致在某个shard上doc ...
- ElasticSearch 评分排序
背景 通过脚本改变评分 背景 近期有一个需求,需要对优惠券可用商品列表加个排序,只针对面值类的券不包括折扣券. 需求是这样的,假设有一张面值券 50 块钱,可用商品列表 A 100.B 40.C 10 ...
- ElasticSearch评分分析 explian 解释和一些查询理解
ElasticSearch评分分析 explian 解释和一些查询理解 按照es-ik分析器安装了ik分词器.创建索引:PUT /index_ik_test.索引包含2个字段:content和nick ...
- WOE:信用评分卡模型中的变量离散化方法(生存分析)
WOE:信用评分卡模型中的变量离散化方法 2016-03-21 生存分析 在做回归模型时,因临床需要常常需要对连续性的变量离散化,诸如年龄,分为老.中.青三组,一般的做法是ROC或者X-tile等等. ...
- 【主流技术】ElasticSearch 在 Spring 项目中的实践
前言 ElasticSearch简称es,是一个开源的高扩展的分布式全文检索引擎. 它可以近乎实时的存储.检索数据,其扩展性很好,ElasticSearch是企业级应用中较为常见的技术. 下面和大家分 ...
- 如何在VS2013中进行Boost单元测试
对于如何在VS2013中进行Boost单元测试,这方面资料太少.自己也因此走了不少弯路.下文将会阐述一下如何在VS2013中进行Boost单元测试. 在开始Boost单元测试之前,我们需要先安装VS2 ...
- ES 02 - 部署Elasticsearch单机服务 + 部署中的常见问题
目录 1 准备工作 1.1 安装JDK 1.2 下载安装包 1.3 创建elastic用户 2 启动ES服务 2.1 修改配置文件 2.2 启动服务 3 验证ES服务是否可用 4 关闭与重启服务 4. ...
- FPGA计算中定标与位扩展的实现
我不知道名字取对没有,在FPGA计算中有时往往需要在不溢出的情况下将数扩大,从而获得更好的计算精度. 比如.在一个8位宽的系统中,将x=0000_0010,算术左移m=5位之后得到xt=0100_00 ...
随机推荐
- div自适应水平垂直居中的方法
1.Flexbox布局: display:flex; justify-content:center; align-items:center; width:100%; 2.Bootstrap栅格布局 一 ...
- Xcode 之 Debug 和 Release 模式切换方式 - iOS
一.选择项目工程,其次选择 Edit Scheme 二.在弹框中选择 Run => Info => Build Configuration 选择中进行 Debug 和 Release 的切 ...
- FreeImage 生成带透明通道的GIF
主要方法: 加载图像及读取参数 FreeImage_Load FreeImage_GetWidth FreeImage_GetHeight FreeImage_Allocate FreeImage_G ...
- 删除文件的第一列 -Linux
删除文件 text中第一列 方式一 awk '{$1="";print $0}' text 方式二 sed -e 's/[^ ]* //' text
- C#程序员快速上手Angular开发
由vue的技术栈快速切换到Angular,对于C#开发人员来说应该不难,二期是一个比较平滑的过渡.所以最近 记录下切换到Angular框架的一些过程,因为NG天然支持Typescript,特别是当项目 ...
- Scala 语法(一)
(1)基本语法 变量 val var(可变变量): 数据类型 Byte,Char,Int,Short,Long,String(字符),Float,Double,Boolean(true,flase). ...
- Python(1-8天总结)
day1:变量:把程序运行过程中产生的中间值.暂时存储起来.方便后面的程序调用.变量命名规范:常量:所有字母大写注释:数据类型: 1. int 整数 2. str 字符串. 不会用字符串保存大量的数据 ...
- C语言学习记录_2019.02.04
逻辑性变量的定义符:bool,在C语言中只有true和false: 定义方式:bool t = true; 逻辑运算符: !:逻辑非 &&:逻辑与 ||:逻辑或 表达区间的错误形式:4 ...
- 转载:隐藏bat窗口在后台运行(找了好久)
https://mp.weixin.qq.com/s?__biz=MzU4MjY1ODA3Nw==&mid=2247484277&idx=1&sn=8b5d98aab3827b ...
- Hibernate学习笔记三
1.1.1 Hibernate的关联关系映射:(多对多) 1.1.1.1 多对多的配置: 步骤一创建实体和映射: Student: public class Student { private Int ...