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 ...
随机推荐
- Oracle 常用脚本
ORACLE 默认用户名密码 sys/change_on_install SYSDBA 或 SYSOPER 不能以 NORMAL 登录,可作为默认的系统管理员 system/manager SYSDB ...
- List、LinkedList、ArrayList、Vector
目前好像写不出比较高质量的随笔,除了多看看别人写的,就是多写,做好自己可以做的 最近听的和看到的最多的一个词就是“勿忘初心”.的确不少人到了一定高度之后,就不知道该怎么做了.(包括我曾经的偶像娜姐,在 ...
- Resharp常用设置收集整理
F12跳转的问题:
- centos7安装mysql5.7.18笔记
重装了一下系统,装了centos7,但是centos7下默认没有安装mysql,有MariaDB数据库,网上的解释是: “MariaDB数据库管理系统是MySQL的一个分支,主要由开源社区在维护,采用 ...
- linux3.4.2之块设备驱动完整程序
/*参考drivers/block/xd.c *以及drivers/block/z2ram.c */ #include <linux/module.h> #include <linu ...
- LeetCode-Algorithms 1. 两数之和
个人练习记录 给定一个整数数组和一个目标值,找出数组中和为目标值的两个数. 你可以假设每个输入只对应一种答案,且同样的元素不能被重复利用. 示例: 给定 nums = [2, 7, 11, 15], ...
- Java基础之static关键字的用法
Java中的static关键字主要用于内存管理.我们可以应用static关键字在变量.方法.块和嵌套类中. static关键字属于类,而不是类的实例. 静态(static)可以是: 变量 ...
- SAP Odata実行命令(2)
前言 $ skiptokenは.アプリケーションに送信されるエントリ数を制限するために使用されます. 膨大な数のエントリが要求された場合.これはパフォーマンスの向上にも役立ちます.次のリンクがアプリケ ...
- 阿里云 Debian 9.2 安装 Java Web 环境
CentOS 源内包太旧,和本地开发环境不兼容的地方太多 系统配置 更新数据库与软件包 # apt-get update && apt-get -y upgrade 提示是否保留本地已 ...
- Redis的n种妙用,不仅仅是缓存
redis是键值对的数据库,常用的五种数据类型为字符串类型(string),散列类型(hash),列表类型(list),集合类型(set),有序集合类型(zset) Redis用作缓存,主要两个用途: ...