千家信息网

ElasticSearch相关性打分机制是什么

发表于:2025-12-01 作者:千家信息网编辑
千家信息网最后更新 2025年12月01日,今天就跟大家聊聊有关ElasticSearch相关性打分机制是什么,可能很多人都不太了解,为了让大家更加了解,小编给大家总结了以下内容,希望大家根据这篇文章可以有所收获。ElasticSearch 2
千家信息网最后更新 2025年12月01日ElasticSearch相关性打分机制是什么

今天就跟大家聊聊有关ElasticSearch相关性打分机制是什么,可能很多人都不太了解,为了让大家更加了解,小编给大家总结了以下内容,希望大家根据这篇文章可以有所收获。

ElasticSearch 2.3版本全文搜索默认采用的是相关性打分TFIDF,在实际的运用中,我们采用Multi-Match给各个字段设置权重、使用should给特定文档权重或使用更高级的Function_Score来自定义打分,借助于Elasticsearch的explain功能,我们可以深入地学习一下其中的机制。

创建一个索引

PUT /gino_test{  "mappings": {    "tweet": {      "properties": {        "text": {          "type": "string",          "term_vector": "with_positions_offsets_payloads",          "store" : true,          "analyzer" : "fulltext_analyzer"         },         "fullname": {          "type": "string",          "term_vector": "with_positions_offsets_payloads",          "analyzer" : "fulltext_analyzer"        }      }    }  },  "settings" : {    "index" : {      "number_of_shards" : 1,      "number_of_replicas" : 0    },    "analysis": {      "analyzer": {        "fulltext_analyzer": {          "type": "custom",          "tokenizer": "whitespace",          "filter": [            "lowercase",            "type_as_payload"          ]        }      }    }  }}

插入测试数据:

简单情况:单字段匹配打分

POST gino_test/_search{  "explain": true,  "query": {    "match": {      "text": "my cup"    }  }}

查询结果: score_simple.json

打分分析:

ElasticSearch目前采用的默认相关性打分采用的是Lucene的TF-IDF技术。

我们来深入地分析一下这个公式:

score(q,d)  =  queryNorm(q)  · coord(q,d)  · ∑ (tf(t,d) · idf(t)² · t.getBoost() · norm(t,d))
  • score(q,d) 是指查询输入Q和当前文档D的相关性得分;

  • queryNorm(q) 是查询输入归一化因子,其作用是使最终的得分不至于太大,从而具有一定的可比性;

  • coord(q,d) 是协调因子,表示输入的Token被文档匹配到的比例;

  • tf(t,d) 表示输入的一个Token在文档中出现的频率,频率越高,得分越高;

  • idf(t) 表示输入的一个Token的频率级别,它具体的计算与当前文档无关,而是与索引中出现的频率相关,出现频率越低,说明这个词是个稀缺词,得分会越高;

  • t.getBoost() 是查询时指定的权重.

  • norm(t,d) 是指当前文档的Term数量的一个权重,它在索引阶段就已经计算好,由于存储的关系,它最终值是0.125的倍数。

注意:在计算过程中,涉及的变量应该考虑的是document所在的分片而不是整个index。

score(q,d) = _score(q,d.f)                                      --------- ①= queryNorm(q) · coord(q,d) · ∑ (tf(t,d) · idf(t)² · t.getBoost() · norm(t,d))= coord(q,d) · ∑ (tf(t,d) · idf(t)² · t.getBoost() · norm(t,d) · queryNorm(q))= coord(q,d.f) · ∑ _score(q.ti, d.f) [ti in q]                  --------- ②= coord(q,d.f) · (_score(q.t1, d.f) + _score(q.t2, d.f))
  • ① 相关性打分其实是查询与某个文档的某个字段之间的相关性打分,而不是与文档的相关性;

  • ② 根据公式转换,就变成了查询的所有Term与文档中字段的相关性求和,如果某个Term不相关,则需要处理coord系数;

multi-match多字段匹配打分(best_fields模式)

POST /gino_test/_search{  "explain": true,  "query": {    "multi_match": {      "query": "gino cup",      "fields": [        "text^8",        "fullname^5"      ]    }  }}

查询结果:score_bestfields.json

打分分析:

score(q,d) = max(_score(q, d.fi)) = max(_score(q, d.f1), _score(q, d.f2))= max(coord(q,d.f1) · (_score(q.t1, d.f1) + _score(q.t2, d.f1)), coord(q,d.f2) · (_score(q.t1, d.f2) + _score(q.t2, d.f2)))
  • 对于multi-field的best_fields模式来说,相当于是对每个字段对查询分别进行打分,然后执行max运算获取打分最高的。

  • 在计算query weight的过程需要乘上字段的权重,在计算fieldNorm的时候也需要乘上字段的权重。

  • 默认operator为or,如果使用and,打分机制也是一样的,但是搜索结果会不一样。

multi-match多字段匹配打分(cross_fields模式)

POST /gino_test/_search{  "explain": true,  "query": {    "multi_match": {      "query": "gino cup",      "type": "cross_fields",      "fields": [        "text^8",        "fullname^5"      ]    }  }}

查询结果:score_crossfields.json

打分分析:

score(q, d) = ∑ (_score(q.ti, d.f)) = ∑ (_score(q.t1, d.f), _score(q.t1, d.f))= ∑ (max(coord(q.t1,d.f) · _score(q.t1, d.f1), coord(q.t1,d.f) · _score(q.t1, d.f2)), max(coord(q.t2,d.f) · _score(q.t2, d.f1), coord(q.t2,d.f) · _score(q.t2, d.f2)))
  • coord(q.t1,d.f)函数表示搜索的Term(如gino)在multi-field中有多少比率的字段匹配到;best_fields模式中coord(q,d.f1)表示搜索的所以Term(如gino和cup)有多少比率存在与特定的field字段(如text字段)里;

  • 对于multi-field的cross_fields模式来说,相当于是对每个查询的Term进行打分(每个Term执行best_fields打分,即看下哪个field匹配更高),然后执行sum运算。

  • 默认operator为or,如果使用and,打分机制也是一样的,但是搜索结果会不一样。这是一个使用operator为or的报文:score_crossfields_or.json

should增加权重打分

为了增加filter的测试,给gino_test/tweet增加一个tags的字段。

PUT /gino_test/_mapping/tweet{  "properties": {    "tags": {      "type": "string",      "analyzer": "fulltext_analyzer"    }  }}

增加tags的标签

POST /gino_test/_search{  "explain": true,  "query": {    "bool": {      "must": {        "bool": {          "must": {            "multi_match": {              "query": "gino cup",              "fields": [                "text^8",                "fullname^5"              ],              "type": "best_fields",              "operator": "or"            }          },          "should": [            {              "term": {                "tags": {                  "value": "goods",                  "boost": 6                }              }            },            {              "term": {                "tags": {                  "value": "hobby",                  "boost": 3                }              }            }          ]        }      }    }  }}

查询结果:score_should.json

打分分析:

增加了should的权重之后,相当于多了一个打分参考项,打分的过程见上面的计算过程。

function_score高级打分机制

DSL格式:

{    "function_score": {        "query": {},        "boost": "boost for the whole query",        "functions": [            {                "filter": {},                "FUNCTION": {},                 "weight": number            },            {                "FUNCTION": {}             },            {                "filter": {},                "weight": number            }        ],        "max_boost": number,        "score_mode": "(multiply|max|...)",        "boost_mode": "(multiply|replace|...)",        "min_score" : number    }}

支持四种类型发FUNCTION:

  • script_score: 自定义的高级打分机制,涉及的字段只能是数值类型的

  • weight: 权重打分,一般结合filter一起使用,表示满足某种条件加多少倍的分

  • random_score: 生成一个随机分数,比如应该uid随机打乱排序

  • field_value_factor: 根据index里的某个字段值影响打分,比如销量(涉及的字段只能是数值类型的)

  • decay functions: 衰减函数打分,比如越靠近市中心的打分越高

来做一个实验。先给index增加一个查看数的字段:

PUT /gino_test/_mapping/tweet{  "properties": {    "views": {      "type": "long",      "doc_values": true,      "fielddata": {        "format": "doc_values"    }  }}

给三条数据分别加上查看数的值:

POST gino_test/tweet/1/_update{    "doc" : {        "views" : 56    }}

最终数据的样子:

执行一个查询:

{  "explain": true,  "query": {    "function_score": {      "query": {        "multi_match": {          "query": "gino cup",          "type": "cross_fields",          "fields": [            "text^8",            "fullname^5"          ]        }      },      "boost": 2,      "functions": [        {          "field_value_factor": {            "field": "views",            "factor": 1.2,            "modifier": "sqrt",            "missing": 1          }        },        {          "filter": {            "term": {              "tags": {                "value": "goods"              }            }          },          "weight": 4        }      ],      "score_mode": "multiply",      "boost_mode": "multiply"    }  }}

查询结果:score_function.json

打分分析:

score(q,d) = score_query(q,d) * (score_fvf(`view`) * score_filter(`tags:goods`))
  • score_mode表示多个FUNCTION之间打分的运算法则,需要注意不同的FUNCTION的打分的结果级别可能相差很大;

  • boost_mode表示function_score和query_score打分的运算法则,也需要注意打分结果的级别;

rescore重打分机制

ES官网介绍: Rescoring | Elasticsearch Reference [2.3] | Elastic

重打分机制并不会应用到所有的数据中。比如需要查询前10条数据,那么所有的分片先按默认规则查询出前10条数据,然后应用rescore规则进行重打分返回给master节点进行综合排序返回给用户。

rescore支持多个规则计算,以及与原先的默认打分进行运算(权重求和等)。

rescore因为计算的打分的document较少,性能应该会更好一点,但是这个涉及到全局排序,实际运用的场景要注意。

看完上述内容,你们对ElasticSearch相关性打分机制是什么有进一步的了解吗?如果还想了解更多知识或者相关内容,请关注行业资讯频道,感谢大家的支持。

字段 查询 权重 机制 相关性 文档 结果 数据 d.f 分析 模式 频率 搜索 输入 运算 得分 过程 高级 内容 类型 数据库的安全要保护哪些东西 数据库安全各自的含义是什么 生产安全数据库录入 数据库的安全性及管理 数据库安全策略包含哪些 海淀数据库安全审计系统 建立农村房屋安全信息数据库 易用的数据库客户端支持安全管理 连接数据库失败ssl安全错误 数据库的锁怎样保障安全 测试数据库工具连接ip 论文软件开发话题描述 未定事件簿2.2支持的服务器 平板电脑数据库在哪 数据库职业发展晋升 丰台区正规软件开发报价 长宁区创新软件开发销售电话 龙族幻想手游服务器不通知 flask 的数据库迁移 厦门觅风网络技术有限公司 计算机网络安全的理论基础 安徽大学数据库应用基础报表 上海飞宇网络技术 数据库与文件系统 金山区专业软件开发哪家好 能转入紫荆城的服务器 软件开发外包驻场一天多少 贷超软件开发 数字科技产业互联网产业 706所笔试软件开发 面试 西城区软件开发公司 降低网络安全风险的方法 阿里子账号看不到数据库 信息网络安全专业能考什么证 吉林银联网络技术服务代理商 群晖服务器查显示硬盘不兼容 数据库cgb是什么意思 同花顺手机连不上服务器 腾讯云服务器被攻击会怎么样 网络安全和编程哪个工资高
0