当我们能使用match来搜索匹配数据的时候,es会给每一个文档进行评分(匹配度),并根据评分的大小对结果文档进行排序。
介绍
es的实时评分机制是基于 Lucene
的基础上实现的,最常见的是 TF/IDF
和BM25
这两种评分模型。
TF-IDF属于向量空间模型,而BM25属于概率模型,但是他们的公式可能并没有你想象的那么大差距。两种相似度模型都使用idf方法和tf方法的某种乘积来定义单个词项的权重,然后把和查询匹配的词项的权重相加作为整篇文档的分数。
对于这两种算法的详细介绍以及区别大家可以参考:
在es5.0版本之前使用了TF/IDF
算法实现,而在5.0之后默认使用BM25
方法实现。
作为开发,我们可以不需要了解非常深入的了解公式的由来,但也要做到公式的组成和每个参数的含义。
例子
下面是一个普通的查询:
PUT /test/test1/1
{
"title":"hallo,books"}
PUT /test/test1/2
{
"title":"hallo,books boy"}
PUT /test/test1/3
{
"title":"hallo hallo,hi hi hi hi"}
PUT /test/test1/4
{
"title":"hallo hallo,hi hi hi hi"}
PUT /test/test1/5
{
"title":"hi hi hi hi"}
GET /test/test1/_search
{
"query": {
"match": {
"title": "hallo hi"
}
}
}
在搜索的结果中有一个_score字段,代表了es给文档的评分,默认的排序规则是根据这个字段的大小进行排序,越大则出现在越前面。
当我们搜索一个单词或者一个词组乃至一句话的时候,es先会通过Analyzer
分析器拆成多个term(ES学习——分析器和自定义分析器),然后在对每一个term进行BM25
公式评分,最后把每一个term的评分进行加权求和,就是最后的得分。
例如,我们搜索hallo hi
,es通过对应的默认解析器拆分成hallo
和hi
,分别求出分数score(hallo)和score(hi):
总得分Score=score(hallo)+score(hi)。
和sql相似,我们可以通过在搜索条件中添加explain=true,来查看具体的得分过程。
GET /test/test1/_search?explain=true
{
"query": {
"match": {
"title": "hallo hi"
}
}
}
##以下通过筛选,过滤了一些无用的信息
{
"_shard": "[test][0]",【1】
"_score": 1.202173,【2】
"_source": {
"title": "hallo hallo,hi hi hi hi"【3】
},
"_explanation": {