网站建站建设价格,莆田网站建设解决方案,vr模式的网站建设公司,网站建设开发公司排名前言
ES 的主查询评分模式分为两种#xff0c;是信息检索领域的重要算法#xff1a; TF-IDF 算法 和 BM25 算法。
Elasticsearch 从版本 5.0 开始引入了 BM25 算法作为默认的文档评分#xff08;relevance scoring#xff09;算法。在此之前#xff0c;Elasticsearch 使…前言
ES 的主查询评分模式分为两种是信息检索领域的重要算法 TF-IDF 算法 和 BM25 算法。
Elasticsearch 从版本 5.0 开始引入了 BM25 算法作为默认的文档评分relevance scoring算法。在此之前Elasticsearch 使用的是 TF-IDF 算法作为默认的文档评分算法。从版本 5.0 起BM25 算法取代了 TF-IDF成为了默认的算法用于计算文档与查询之间的相关性得分。 这个变化主要是为了更好地适应现代信息检索需求BM25 算法在一些情况下能够提供更准确的文档排序和检索结果。 而 Function Score Query 不夸张的说是 ES 里面终极自定义打分的大招非常的灵活并且功能强大常规情况下我们排序都是基于 _score 的如果 _score相等的情况下我们还可以额外增加排序字段比如按日期数量价格等但在搜索引擎中排序往往并不像 SQL 那样从左到右规整的按照多字段排序在 SQL 里面排序的主顺序一定是由左边的第一个字段决定的但在搜索引擎种却不仅仅是这样的还可以通过 function score 做到那个字段贡献的分值大排序顺序就以谁为主因为这些是真实存在的需求场景如下
新闻场景搜索具有某个关键词的文档同时结合文档的时效性进行综合排序导航场景搜索某个地点附近的饭店同时根据距离远近和价格等因素综合排序论坛场景搜索包含某个关键词的文章同时根据浏览次数和点赞数进行综合排序 SQL 的排序模型
select * from table order by A, B, C
搜索引擎的排序模型
query * from index oder by score max(A, B, C)
写入数据
为了用实际例子讲解 function score我们先写入几条数据
POST test01/doc/_bulk
{ index : { _id : 1 } }
{title: kubernetes, content: Development History,vote: 3,year: 2015}
{ index : { _id : 2 } }
{title: kubernetes, content: Competitive Analysis,vote: 5,year: 2018}
{ index : { _id : 3 } }
{title: kubernetes docker,content: The connection between virtual and docker technology,vote: 100,year: 2011}
{ index : { _id : 4 } }
{title: kubernetes network,content: router vlan tcp,vote: 20,year: 2009} 查询数据
查询关键词kubernetes
GET test01/_search?search_typedfs_query_then_fetch
{query: {bool: {should: [{term: {title: kubernetes}}]}},explain: false
}
返回结果 hits : [{_index : test01,_type : doc,_id : 2,_score : 0.12776,_source : {title : kubernetes,content : Competitive Analysis,vote : 5,year : 2018}},{_index : test01,_type : doc,_id : 1,_score : 0.12776,_source : {title : kubernetes,content : Development History,vote : 3,year : 2015}},{_index : test01,_type : doc,_id : 4,_score : 0.09954306,_source : {title : kubernetes network,content : router vlan tcp,vote : 20,year : 2009}},{_index : test01,_type : doc,_id : 3,_score : 0.081535265,_source : {title : kubernetes mesos swarm,content : The connection between virtual and docker technology,vote : 100,year : 2011}}]
结果看起来是正常的ok现在我们要改变需求了加入了基于点赞量的加权也就是说匹配关键词并且点赞量高的优先展示因为点赞量高意味着这些文章质量更高所以需要优先曝光这个时候我们就需要用到 function score
Function Score Query介绍
计算原理
使用主查询 的 TF-IDF 或者 BM25 算法得出来的默认评分简称为 query_score
使用 Function Score 查询结合自定义策略得出来的评分简称为function_score
最终用于排序的评分称为 sort_score 在使用了 自定义的 Fuction Score 之后我们最终得出来的 sort_score 就是使用 query_score 和 function_score以某种运算形式 (score_mode) 计算出来的这个策略默认是相乘也即
sort_score query_score * function_score
function_score内的score_mode
score_mode有六种 mode 描述 multiply 多个函数 score 相乘默认 sum 多个函数 score 求和 avg 多个函数 score 取平均值 first 使用第一个 filter 函数的 score max 取多个函数 score 中最大的那个 min 取多个函数 score 中最大的那个
sort_score运算策略
sort_score 是 query_score 和 function_score以某种形式运算而来支持的运算操作也有六种 mode 描述 multiply sort_score query_score * function_score默认 sum sort_score query_score function_score avg sort_score avg ( query_score function_score ) / 2 replace sort_score function_score max sort_score max ( query_score function_score ) min sort_score min ( query_score function_score )
默认情况下修改分数不会更改匹配的文档。要排除不满足特定分数阈值的文档可以将 min_score 参数设置为所需的分数阈值 fuction score的评分函数
script_score
script_score 支持自定义脚本打分也就是说可以用类编程语言的脚本来嵌入的打分逻辑ES 之前用的是 groovy脚本因安全性有问题现在换成了 Painless 脚本详细可参考Painless scripting language | Elasticsearch Guide [8.9] | Elastic
现在我们用 script_score 来完成上面查询场景中的给点赞量的加权
GET test01/_search?search_typedfs_query_then_fetch
{query: {function_score: {query: {match: { title: kubernetes }},script_score: {script: {params: {baseScore: 1},source: params.baseScore doc[vote].value}},boost_mode: replace,score_mode: multiply}},explain: false
} 结果如下 hits : [{_index : test01,_type : doc,_id : 3,_score : 101.0,_source : {title : kubernetes mesos swarm,content : The connection between virtual and docker technology,vote : 100,year : 2011}},{_index : test01,_type : doc,_id : 4,_score : 21.0,_source : {title : kubernetes network,content : router vlan tcp,vote : 20,year : 2009}},{_index : test01,_type : doc,_id : 2,_score : 6.0,_source : {title : kubernetes,content : Competitive Analysis,vote : 5,year : 2018}},{_index : test01,_type : doc,_id : 1,_score : 4.0,_source : {title : kubernetes,content : Development History,vote : 3,year : 2015}}]
在这个函数查询中我们使用了 replace 策略来直接使用 fuction_score的分数注意 从 docValue 里面取出来的字段必须是number 类型才可以
weight
直接对查询加权
例子一
GET test01/_search?search_typedfs_query_then_fetch
{query: {function_score: {query: {match: { title: kubernetes }},weight: 10}},explain: false
}结果 hits : [{_index : test01,_type : doc,_id : 2,_score : 1.2775999,_source : {title : kubernetes,content : Competitive Analysis,vote : 5,year : 2018}},{_index : test01,_type : doc,_id : 1,_score : 1.2775999,_source : {title : kubernetes,content : Development History,vote : 3,year : 2015}},{_index : test01,_type : doc,_id : 4,_score : 0.9954306,_source : {title : kubernetes network,content : router vlan tcp,vote : 20,year : 2009}},{_index : test01,_type : doc,_id : 3,_score : 0.8153527,_source : {title : kubernetes mesos swarm,content : The connection between virtual and docker technology,vote : 100,year : 2011}}]
例子二
GET test01/_search?search_typedfs_query_then_fetch
{query: {function_score: {query: {match_all: {}},functions: [{filter: { match: { content: kubernetes } },weight: 1},{filter: { match: { title: mesos } },weight: 10},{filter: { match: { content: tcp } },weight: 20}]}},explain: false
}
结果如下 hits : [{_index : test01,_type : doc,_id : 4,_score : 20.0,_source : {title : kubernetes network,content : router vlan tcp,vote : 20,year : 2009}},{_index : test01,_type : doc,_id : 3,_score : 10.0,_source : {title : kubernetes mesos swarm,content : The connection between virtual and docker technology,vote : 100,year : 2011}},{_index : test01,_type : doc,_id : 2,_score : 1.0,_source : {title : kubernetes,content : Competitive Analysis,vote : 5,year : 2018}},{_index : test01,_type : doc,_id : 1,_score : 1.0,_source : {title : kubernetes,content : Development History,vote : 3,year : 2015}}]
这个 filter 很适合竞价排名
random_score
random score 相当于把返回文档的顺序给打乱比较适合随机召回文档
GET test01/_search?search_typedfs_query_then_fetch
{query: {function_score: {query: {match_all: {}},random_score: {}}},explain: false
}
默认情况下是每次查询的值都是随机的但有时候我们想用同一个 id 的保持不变不同 id 的结果随机这个时候可以使用 seed 和 field 来控制 GET test01/_search?search_typedfs_query_then_fetch
{query: {function_score: {query: {match_all: {}},random_score: {seed: 10,field: _seq_no}}},explain: false
}
这个时候 seed 的值就可以等同于 idid 值一样的结果不变
field_value_factor
GET test01/_search?search_typedfs_query_then_fetch
{query: {function_score: {query: {match: {title:kubernetes}},field_value_factor: {field: vote,factor: 1.2,modifier: sqrt,missing: 1},boost_mode: max}},explain: false
}
等价于script score 脚本 sqrt(1.2 * doc[vote].value)
其中field 是文档种的字段missing 是缺失值factor 是放大的比值默认是 1modifier 是对结果的再次处理支持多种函数如none, log, log1p, log2p, ln, ln1p, ln2p, square, sqrt, or reciprocal
decay functions
衰减函数
以某个数值作为中心点距离多少的范围之外逐渐衰减缩小分数以某个日期作为中心点距离多久的范围之外逐渐衰减缩小分数以某个地理位置点作为中心点方圆多少距离之外逐渐衰减缩小分数
一个例子
DECAY_FUNCTION: { FIELD_NAME: { origin: 11, 12,scale: 2km,offset: 0km,decay: 0.33}
}
上例的意思就是在距中心点方圆 2 公里之外分数减少到三分之一乘以 decay 的值 0.33
DECAY_FUNCTION 可以是以下任意一种函数
linear : 线性衰减函数
exp : 指数衰减函数
gauss : 高斯正常衰减函数
origin :
用于计算距离的原点。对于数字字段必须以数字形式给出对于日期字段必须以日期形式给出对于地理字段必须以地理点形式给出。地理和数字字段是必需的。对于日期字段默认值为现在。 origin 支持日期数学例如 now-1h
scale :
定义计算得分等于衰减参数时距原点 偏移量的距离。对于地理字段可以定义为数字单位1km、12m、...。默认单位是米。对于日期字段可以定义为数字单位“1h”、“10d”、...。默认单位是毫秒。对于数字字段任何数字
offset :
如果定义了偏移量则衰减函数将仅计算距离大于定义的偏移量的文档的衰减函数。默认值为 0
decay :
衰减参数定义如何在给定比例的距离上对文档进行评分。如果未定义衰减则距离尺度上的文档将评分为 0.5 例如现在新数据标题匹配 kubernetes 后按照优先检索位于 2011-2015 年份进行加权不再按照点赞量
GET test01/_search?search_typedfs_query_then_fetch
{query: {function_score: {query: {match: {title:kubernetes}},gauss: {year: {origin: 2013, offset: 2,scale: 2,decay: 0.1 }},boost_mode: max}},explain: false
}
解释一下
上面使用高斯函数作为衰减使用的是年份字段
orgin代表中心点是 2013 年
offset2 代表 [2011, 2015] 作为中心圆也就是 [2011, 2015]位于这之间的文档评分直接为 1
scala: 2 代表 [2009, 2017]之外的评分为 0.1
其他的如果位于 2009-2011 范围的以及 2015-2017 范围的就按正常评分就好了
结果如下 hits : [{_index : test01,_type : doc,_id : 3,_score : 1.0,_source : {title : kubernetes mesos swarm,content : The connection between virtual and docker technology,vote : 100,year : 2011}},{_index : test01,_type : doc,_id : 1,_score : 1.0,_source : {title : kubernetes,content : Development History,vote : 3,year : 2015}},{_index : test01,_type : doc,_id : 2,_score : 0.12776,_source : {title : kubernetes,content : Competitive Analysis,vote : 5,year : 2018}},{_index : test01,_type : doc,_id : 4,_score : 0.1,_source : {title : kubernetes network,content : router vlan tcp,vote : 20,year : 2009}}]
三种衰减的函数的曲线如下 此外如果用于计算衰减的字段包含多个值则默认情况下会选择最接近中心点的值来确定距离。这可以通过设置 multi_value_mode 来更改
min距离是最小距离
max距离是最大距离
avg距离是平均距离
sum距离是所有距离的总和 DECAY_FUNCTION: {FIELD_NAME: {origin: ...,scale: ...},multi_value_mode: avg} function score 的其他参数
max_boost: 最大权重值的范围
boost_mode: 最终 query_score 和 function_score的计算策略
min_score: 最终的结果过滤掉评分低于这个值的