es head 复合查询_【ES进阶】深入理解Elasticsearch检索评分score执行计划及逆向文档词频idf...

2023-11-19

在前面的课程中,通过搭建ELK相关的中间件,以及配置动态mapping结构用于存储我们需要检索的文档信息;

我们通过输入关键词进行分词检索然后ES默认通过评分的形式将数据排序好展示给我们,当文档评分越高,那么搜索的结果越靠前;如下图所示,我们通过百度搜索关键字"兔子李磊"得到的搜索结果

可以看到,在上述搜索结果中,可以看到第一条记录中,由于兔子 和 李磊 两个关键词都出现了,排名相对靠前一点;我们暂时可以理解为上述第一条文章的搜索结果相对搜索评分较高,相关度较高;

上述的理论基于一些自我逻辑,那么在ES中,我们搜索的相关度评分,又是如何计算出来的呢;

我们通过ES的复合框搜索语句到结果展示,其展示规则默认就是根据相关度进行排序的,即默认根据score排序;

查询ES的执行计划

执行计划查询方式如下:

GET shopping/_search
{
  "explain": true, 
  "query": {
    "match": {
        "goodsInfoName": "苏泊尔"
    }
  }
}

在上述DSL语句中,开启explain即可开启ES的查询计划(类似于Mysql数据库的执行计划);

上述DSL语句在我本地的查询结果如下:

{
  "took" : 1,
  "timed_out" : false,
  "_shards" : {
    "total" : 3,
    "successful" : 3,
    "skipped" : 0,
    "failed" : 0
  },
  "hits" : {
    "total" : {
      "value" : 24,
      "relation" : "eq"
    },
    "max_score" : 5.3067513,
    "hits" : [
      {
        "_shard" : "[shopping][1]",
        "_node" : "h665-yAdSzGgjxamBh5CjA",
        "_index" : "shopping",
        "_type" : "_doc",
        "_id" : "10976",
        "_score" : 5.3067513,
        "_source" : {
           "goodsInfoName" : "苏泊尔不锈钢压力锅高压锅YS22ED+苏泊尔保鲜盒饭盒便当盒330mlKB033AE1(银色)",
           "其他字段省略....."
        },
        "_explanation" : {
          "value" : 5.3067513,
          "description" : "weight(goodsInfoName:苏泊尔 in 328) [PerFieldSimilarity], result of:",
          "details" : [
            {
              "value" : 5.3067513,
              "description" : "score(freq=2.0), computed as boost * idf * tf from:",
              "details" : [
                {
                  "value" : 2.2,
                  "description" : "boost",
                  "details" : [ ]
                },
                {
                  "value" : 3.6549778,
                  "description" : "idf, computed as log(1 + (N - n + 0.5) / (n + 0.5)) from:",
                  "details" : [
                    {
                      "value" : 10,
                      "description" : "n, number of documents containing term",
                      "details" : [ ]
                    },
                    {
                      "value" : 405,
                      "description" : "N, total number of documents with field",
                      "details" : [ ]
                    }
                  ]
                },
                {
                  "value" : 0.65996563,
                  "description" : "tf, computed as freq / (freq + k1 * (1 - b + b * dl / avgdl)) from:",
                  "details" : [
                    {
                      "value" : 2.0,
                      "description" : "freq, occurrences of term within document",
                      "details" : [ ]
                    },
                    {
                      "value" : 1.2,
                      "description" : "k1, term saturation parameter",
                      "details" : [ ]
                    },
                    {
                      "value" : 0.75,
                      "description" : "b, length normalization parameter",
                      "details" : [ ]
                    },
                    {
                      "value" : 11.0,
                      "description" : "dl, length of field",
                      "details" : [ ]
                    },
                    {
                      "value" : 13.553086,
                      "description" : "avgdl, average length of field",
                      "details" : [ ]
                    }
                  ]
                }
              ]
            }
          ]
        }
      },
      .....略.....

通过查询ES的执行计划(explain)我们可以得出,score评分基础公式如下:score(freq=2.0), computed as boost * idf * tf from:

如果查询关键字被分词为多个词组,那么score评分等于每个关键词的score评分总和;

ES执行计划详解

上述DSL语句查询结果中,查询总耗时为1毫秒(took),当前查询索引有3个分片(_shards.total),当前查询共查询到24条记录(hits.value),当前查询最大查询相关度评分为5.3067513分(hits.max_score),当前查询的第一条记录是从分片编号为1的分片中查询出来的(hits.hits._shard)......

"description" : "weight(goodsInfoName:苏泊尔 in 328) [PerFieldSimilarity], result of:" 查询关键词 苏泊尔 在文档id为328记录中的查询字段goodsInfoName的打分情况;

其中查询结果集的第一条记录的执行计划部分代码为 hits.hits._explanation,其评分为5.3067513分,其评分的计算方式为

"description" : "score(freq=2.0), computed as boost * idf * tf from:"

在这里,有三个关键词含义分别如下:
boost:查询时候查询项加权值,当前值可以通过创建mapping结构的时候指定,也可以在后期查询的时候动态修改

idf:
反转文档词频,意思是出现的逆词频数,意为查询到的文档记录数和索引中总文档数的一个占比关系,其计算公式如下:
"description" : "idf, computed as log(1 + (N - n + 0.5) / (n + 0.5)) from:"

tf: 词频归一值,即搜索的关键词(未分词或分词后的词组)在被搜索的字段的(未分词或分词后的词组)中所出现的个数对总的分词后的词组数的比例,其计算公式如下:
"description" : "tf, computed as freq / (freq + k1 * (1 - b + b * dl / avgdl)) from:"
在上述DSL语句中,goodsInfoName字段中出现了2次查询关键词"苏泊尔",而排在第二条记录的当前字段中只出现了1次(两条记录分词词组数量相同),
所以在tf评分中,第一条记录的评分高于第二条记录,从而影响到整体评分的走向


根据上述执行计划中的三项评分相乘,从而得到文档的最终score评分值
2.2 * 3.6549778 * 0.65996563 = 5.3067513

ES中评分加权项

boost:对于每一个term的权值,其默认值为2.2,我们可以在创建索引mapping结构的时候指定字段的boost的值,更多情况下,我们可以使用bosst来作为ES搜索结果的调优方案,比如搜索文档标题我们可以将boost权重设置大一些,在搜索文档内容的时候,我们可以将boost权重设置小一些,从而实现动态的调整搜索结果,实现搜索不同的字段计算权重不同;

ES中评分反转文档词频

idf:反转文档词频,上述搜索结果中的explain解释为:

{
  "value" : 3.6549778,
  "description" : "idf, computed as log(1 + (N - n + 0.5) / (n + 0.5)) from:",
  "details" : [
    {
      "value" : 10,
      "description" : "n, number of documents containing term",
      "details" : [ ]
    },
    {
      "value" : 405,
      "description" : "N, total number of documents with field",
      "details" : [ ]
    }
  ]
}

idf打分由log(1 + (N - n + 0.5) / (n + 0.5))公式计算出来的此时log是以e为底数的,由于版本迭代关系,ES中关于idf的算法也在逐步优化,通过公式我们可以看到,我们使用科学计算器以e为底计算两个变量的值发生改变时,idf的得分的变化情况如下

说到这里,我们需要了解一下N 和 n之间的关系;N表示的是当前查询记录所处的分片上当前索引的文档数如果我们有多个分片,那么索引数据会被存储到多个分片上,每个分片上的文档记录数相加,得到的就是当前索引的文档总计录数了;(网上找了很多文章,一直没理解到N的值是如何计算出来的,因为网上都说N的值为文档的总记录数,但是忽略了分片的存在,所以导致学习过程中出现了较多的疑惑);如上面的这个执行计划我们可以看到当前分片"_shard" : "[shopping][1]"中记录了405条shopping索引的记录;

另外省略掉的部分分别从"_shard" : "[shopping][0]" 和 "_shard" : "[shopping][2]" 查询到的记录值,所存储的记录值分别为358、384;这三个数值相加刚好等于我这边shopping索引的总文档记录数1147;

同理,n的值表示从当前分片中匹配到的文档记录数,如上述执行计划结果所示,一共查询到总计录为24,当前分片"_shard" : "[shopping][1]"中匹配到了10条记录,另外所省略掉的部分分别从"_shard" : "[shopping][0]" 和 "_shard" : "[shopping][2]" 匹配到记录值为5 和 9;这三个数值相加就刚好等于24了;

这样的话我们就更容易理解idf分支的计算由来了;如何理解呢,就好比一部《西游记》电视剧一共100集,每一集都有“孙悟空”这个角色出现,那么计算关键词“孙悟空”的idf打分为:log(1 + (100 - 100 + 0.5) / (100 + 0.5)) = 0.0049627893421 ,这样就计算的“孙悟空”相关的文档的idf分数比较低,因为在每一集中都有;

相反,如果100集电视剧中,"白骨精"出现了2集,那么计算"白骨精"的idf分数为:log(1 + (100 - 2 + 0.5) / (2 + 0.5)) = 3.698829785;

所以在搜索"孙悟空" 和 "白骨精" 时,后者的评分会远高于前者; 如果同时搜索“孙悟空和白骨精”,这样分词得到的词组为 [“孙悟空”, “白骨精”], 那么不出意外的话,包含“白骨精” 的文档得分会远高于只包含“孙悟空”的文档; 写的有一点绕,意思就是在当前分片中,搜索匹配到的文档越多,词频整体出现的越高,得分越低;

ES中评分词频归一值

tf:词频,又称为 词频归一值,即搜索的关键词(未分词或分词后的词组)在被搜索的字段的(未分词或分词后的词组)中所出现的个数对总的分词后的词组数的比例;在上述执行计划中解释如下

{
  "value" : 0.65996563,
  "description" : "tf, computed as freq / (freq + k1 * (1 - b + b * dl / avgdl)) from:",
  "details" : [
    {
      "value" : 2.0,
      "description" : "freq, occurrences of term within document",
      "details" : [ ]
    },
    {
      "value" : 1.2,
      "description" : "k1, term saturation parameter",
      "details" : [ ]
    },
    {
      "value" : 0.75,
      "description" : "b, length normalization parameter",
      "details" : [ ]
    },
    {
      "value" : 11.0,
      "description" : "dl, length of field",
      "details" : [ ]
    },
    {
      "value" : 13.553086,
      "description" : "avgdl, average length of field",
      "details" : [ ]
    }
  ]
}

tf词频归一值的计算公式由freq / (freq + k1 * (1 - b + b * dl / avgdl)) 组成,可以看到一共有5个关键词;

归一在ES中是一个比较重要的打分标准,和idf一样;不过idf是针对检索结果记录数与总记录数之间的关系来计算的得分,而归一值则是通过计算单个文档内部的查询结果进行打分;

通俗易懂的描述,即查询的关键词(词组)在被检索字段的分词后词组中出现的评率越高,其归一值分数相对越好;在ES中,针对不需要分词的字段(keyword)类型的默认是关闭归一值的;

freq:检索关键词组在被检索字段的词组中出现的频率,即出现了多少次,比如上面的执行计划搜索 苏泊尔 在字段中出现了2次,其结果为2

k1:词的饱和度值,默认值为1.2 (没有深入去了解)

b:长度归一化参数,默认值为0.75 (没有深入去了解)

d1:被检索字段分词后的词组长度,比如上面的执行计划搜索结果第一条搜索的关键字段是 goodsInfoName,其分词后一共产生了11个词组,所以在第一条记录的执行计划中,d1的值为 11;通过上面的公式可以看到,d1出现在分母的位置,即d1的值越大,其计算的评分会越小;

avgdl:分片中当前被检索字段的平均词组数值;即在当前分片中当前索引每个文档中当前字段 goodsInfoName 拆分的词组数量 的平均值;不同的分片中avgdl的值可能是不一样的;因为不同的字段存储的内容不同,每个字段的avgdl也是不一样的,当我们多字段查询时,相比较title之类的字段可以获取的评分相对会更高,因为词组更短;为了均衡这一规律,实现归一值,所以除以avgdl从而获取一个相对比较平和的比较分数,获取的分数更加客观;

总结:ElasticSearch的score字段搜索评分由3个部分组成,分别是boost、idf、tf;score(freq=2.0), computed as boost * idf * tf from:

增加关键词的多元化 和 提升关键词在单文档中出现的频率等都可以直接影响到ES检索的打分;

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

es head 复合查询_【ES进阶】深入理解Elasticsearch检索评分score执行计划及逆向文档词频idf... 的相关文章

  • 在echarts中自定义提示框内容

    以折线图为例 在鼠标滑过每个数据标签时 为了更友好地显示数据内容 需要对显示的数据内容作格式化处理 添加自定义内容 这就需要用到tooltip的formatter属性的回调函数 本文将从配置代码和效果两方面来展示它的使用 柱状图的原理类似
  • NCC低代码平台服务搭建指南

    NCC服务搭建 前言 本文档旨在帮助第一次接触NCC的开发人员 搭建NCC开发环境 1 NCC相关资料 开发者社区 https nccdev yonyou com 资料 https pan baidu com s 15V71U7vVOGr8
  • 【论文笔记】TNASP:A Transformer-based NAS Predictor with a Self-evolution Framework

    文章目录 0 摘要 摘要解读 1 Introduction 2 相关工作 3 方法 3 1 Training based network performance predictors 3 2 基于Transformer的预测器 3 3 自演
  • unity3d实现简单的打飞碟游戏

    游戏内容 游戏有n个round 每个round发射10次trial 每个trial的飞碟都可能不同 包括速度角度得分等 使用鼠标进行射击 点中即表示射击成功 游戏要求 使用带缓存的工厂模式来管理飞碟的生产与再利用 工厂使用单例模式 游戏的设
  • python中.argsort()的用法

    argsort 是对数组参数从小到大排序 然后取出排序后的索引 例如 a np array 0 2 0 5 0 3 0 4 a argsort 输出的就是对a数组排序过后的索引 0 2 3 1
  • 三、web端显示之hdfs基本操作

    三台的节点均启动成功之后 完全匹配的上配置的下图所示情况 若启动不成功 则先 root hadoop1 hadoop 3 1 3 stop all sh 再输入ll显示一下 删除每一个集群上的data和logs root hadoop1 h
  • Qt源代码中二进制兼容及d、q指针的理解

    1 二进制兼容的理解 首先按照本文对二进制兼容进行理解 此处是本人的总结 将类的私有属性 不需要暴露的部分 放到私有类中 在类中定义私类的指针进行交互 指针的大小是已知不变的 指针数据类型为Int 4个字节 软件发布后只需要改私类中的部分
  • 安装vmware tools时,kernel版本不匹配问题的解决方法

    安装vmware tools 的时候 提示找不到C header files 此种情况下 按以下步骤操作 1 内核安装完毕后 需要用这个命令确定内核 C header 的安装目录 ls d usr src kernels uname r i
  • 怎样知道自己适不适合做程序员

    编程是一门非常有技术含量的手艺活 待遇和福利相对来说较为丰厚 由于种种原因想要转行做程序员的人 总会有这样的困惑 我是否适合做程序员呢 其实做为一个开发者 有一个学习的氛围跟一个交流圈子特别重要这里我推荐一个C语言C 交流群58365041
  • 全文检索几种词向量模型

    1 倒排索引模型 2 布尔检索类型 3 TF IDF权重计算 下面是TF IDF的JAVA代码实现 public class TFIDF public double tf List
  • vue的循环遍历(v-for)

    1 循环遍历 1 循环遍历 vue的循环遍历用v for 语法类似于js中的for循环 当我们有一组数据需要进行渲染时 我们就可以使用v for来完成 2 v for使用格式 格式为 v for item in items 遍历items中
  • 【Android开发】一文全面解析Framework层

    前言 上一篇文章从Native角度讲解了Android进程管理的相关概念 本文将继续从上层的Framework中的进程启动 销毁场景和优先级处理 以及它们与四大组件的种种关联 来逐步解析Android进程管理的其他关键要素 进程的启动 An
  • 腾讯 Bugly 和 CrashHandler 冲突,不上传日志

    简单介绍 CrashHandler 是继承 UncaughtExceptionHandler 类来处理 app 崩溃 自由度比较大 可以收集日志信息保存到本地 上传网络 并重启应用 可以说是除了三方的异常上报工具 开发者使用最多的一种方式
  • Android Log系统介绍

    前言 日志分析是开发的核心阶段之一 开发人员经常会遇到这样那样的问题 需要借助日志分析来解决 Bug日志有助于在开发阶段识别Android应用中的Bug 一旦应用发布到市场上 开发者 或者支持工程师 也要通过分析bug日志来解决问题 可见
  • EditText横屏键盘全屏的问题

    在EditText的属性 android imeOptions flagNoExtractUi flagNoFullscreen 可以解决问题 一定要设置flagNoFullscreen否则会出现一个切换回竖屏后页面显示不全的问题
  • Citrix_XenDesktop7.5安装图解,实现Citrix虚拟云桌面

    Cirtrix XenDesktop 7 5 安装图解 一 安装 XenDesktop 7 5 安装 Winodws 2012 并加入域 xenad local 计算机名为 xd xenad local 过程略 安装 XenDesktop
  • 【计算机网络09】传输层之TCP连接管理

    文章目录 1 深入理解序号seq 确认号ack 2 建立连接 三次握手 2 1 状态解读 2 2 前 2 次握手的特点 2 3 为什么建立连接要进行 3 次握手 2 次不行吗 2 4 第 3 次握手失败了会怎么处理 3 释放连接 四次挥手
  • 什么是库-适用于当前软件的包

    源头 scrapy学习 scrapy第三方模块 不管官网原理 架构 安装等辅助教程多么花枝招展 最后还是落实到下面第3条说的库的特征 都会体现在lib下的site packages下的scrapy模块里 就是一串串的代码而已 重点 1 内置
  • Python爬虫的scrapy的学习(学习于b站尚硅谷)

    目录 一 scrapy 1 scrapy的安装 1 什么是scrapy 2 scrapy的安装 2 scrapy的基本使用 1 scrap的使用步骤 2 代码的演示 3 scrapy之58同城项目结构和基本方法 注 58同城的数据不是公开数

随机推荐

  • 关于子线程的异常捕获 - UncaughtExceptionHandler

    一 为什么需要Thread UncaughtExceptionHandler 1 主线程可以轻松找到异常 但是子线程不行 子线程异常问题 author xuehw date 2020 03 05 public class Exception
  • go的单元测试介绍

    一 问题引出 在我们工作中 我们会遇到这样的情况 就是去确认一个函数 或者一个模块的结果是否正确 例如 我们会遇到测试下面函数是否正确 func addUpper n int int res 0 for i 1 i lt n i res i
  • 转JSON报错怎么办?增加发生js错误时候的代码强壮性

    在js中有些内置方法在使用的时候当传入意外类型参数的时候会报错卡死导致直接让整个项目都跑不起来了 比如 今天 这里就说一个增加代码强壮性的方法 try catch finally 众所周知 try catch 是处理意外错误时候的语句 主要
  • 《R语言实战》学习笔记:第一章 R语言介绍

    R语言实战 学习笔记 第二章 创建数据集 R语言实战 学习笔记 第三章 图像初阶 R语言实战 学习笔记 第四章 基本数据管理 R语言实战 学习笔记 第五章 高级数据管理 R语言介绍 数值运算 age lt c 1 3 5 2 11 9 3
  • 【Zabbix实战之部署篇】Zabbix的分布式监控部署

    Zabbix实战之部署篇 Zabbix的分布式监控部署 一 Zabbix proxy介绍 1 Zabbix proxy简介 2 Zabbix proxy 使用场景 3 Zabbix的分布式监控拓扑 二 检查本地环境 1 本地环境规划 2 检
  • React中文

    1 Hello World 开始React最简单的方式是在CodePen上使用HelloWorld例子 你不需要安装任何东西 你只要在新的标签页中打开并和我们一起看例子 如果你想要使用一个本地开发环境 可参看Installation页 最小
  • Palindrome Partitioning II

    Calculate and maintain 2 DP states pal i j which is whether s i j forms a pal d i which is the minCut for s i n 1 Once w
  • Java NIO实现WebSocket服务器

    简介 在HTTP请求中 服务器往往处于被动的一方 通常都是客户端向服务器发送请求时 服务器才会做出响应 服务器并不会主动向客户端推送消息 因此WebSocket API就为此诞生 WebSocket API是HTML5中的一大特色 能够使得
  • 第三方对接-支付宝支付接入教程

    对接支付宝支付接口 官方文档已经写的很清楚了 但是也有很多小白 第一次对接支付宝支付接口 会有些迷茫 所以我在此写下这篇文章 如果你已经支付宝对应 第一步 创建应用与配置密钥已经熟悉了 这里可以不用看这篇文章了 第一步 创建应用 开发者使用
  • python使用Queue(避坑指南)

    python Queue 常见的队列类别 常见的索取 判断函数 避坑部分 常见的队列类别 class one 普通队列 先进先出 from queue import Queue 导入 temp Queue maxsize 5 申请一个能存放
  • 时间、时间戳互转、日期格式化、获取各种天数

    我们在工作中经常遇到日期格式的转换 比如获取当前时间 转换当前时间格式为2023 09 09 2023 09 09 2023 09 09 18 12 01 时间戳 时间戳转日期 日期转时间戳 获取当前季度 获取上一季度 获取下一季度 获取下
  • java编辑pdf(itextpdf)

    工作上遇到一个小需求 需要在原有的pdf文件上添加一行文字 实现方式如下 引入依赖
  • STM32Cube学习(5)——PWM

    1 引言 单片机 STM32F407ZGT6 仿真器 ST Link V2 开发环境 STM32CubeIDE 1 10 1 功能说明 使用单片机定时器产生PWM实现呼吸灯效果 前情提要 STM32Cube学习 1 点灯 配置 STM32C
  • 使用DataGrip连接SQL Server 2017数据库

    微软的SQL Server数据库是做 NET开发的好朋友 现在最新的版本是2017 SQL Server数据库有自己的Management Studio工具 基本用起来和Visual Studio差不多 当然除了官方的工具之外 其他的数据库
  • Docker安装mysql8.0文档

    第一步需要安装Docker基础环境 具体可以看看这篇 docker基础篇 第二步 拉取mysql8 0的镜像 docker pull mysql 8 0 第三步 镜像启动和文件挂载 复制下面命令执行 33006是对外访问暴露的端口 当然你也
  • python的数据类型有哪些其中哪些是不可变的_python可变数据类型有哪些

    将python3的基本数据类型有六种 Number int float bool complex String List Tuple Dictionary Set 可变数据类型 list dic set 不可变数据类型 Number Str
  • IntelliJ IDEA使用教程

    文章目录 1 IntelliJ IDEA首创项目 2 外观样式 3 类的相关操作 4 模块 1 IntelliJ IDEA首创项目 project 微信主界面 module 下栏 消息 通讯录 发现 我 package 聊天记录 文字 图片
  • SSH密钥过期

    我去 很久没用这个项目 突然发现repo sync 不好用了 发现原来是SSH密钥过期了 1 查看id rsa pub是否存在 ls ssh 2 将里面的东西复制出来 3 重新添加下 SSH Public Key 4 再次运行 repo s
  • 我的和unity3d的小故事1——恶魔射手之鼠标控制移动之input.getaxis("Horizontal")与input.getaxis("Vertical")

    跟着恶魔射手视频学习的过程中遇到的第一个问题是怎么也移动不了 那么问题来了 打印出来是获得的下面两个值都是0 怎么办呢 改edit下面的projectsetting里面的input属性下面两个值的type都改成mouse movement
  • es head 复合查询_【ES进阶】深入理解Elasticsearch检索评分score执行计划及逆向文档词频idf...

    在前面的课程中 通过搭建ELK相关的中间件 以及配置动态mapping结构用于存储我们需要检索的文档信息 我们通过输入关键词进行分词检索然后ES默认通过评分的形式将数据排序好展示给我们 当文档评分越高 那么搜索的结果越靠前 如下图所示 我们