什么是相关性?
我们曾经讲过,默认情况下,返回结果是按相关性倒序排列的。 但是什么是相关性? 相关性如何计算?
每个文档都有相关性评分,用一个正浮点数字段 _score 来表示 。 _score 的评分越高,相关性越高。
查询语句会为每个文档生成一个 _score 字段。评分的计算方式取决于查询类型 不同的查询语句用于不同的目的: fuzzy 查询会计算与关键词的拼写相似程度,terms 查询会计算 找到的内容与关键词组成部分匹配的百分比,但是通常我们说的 relevance 是我们用来计算全文本字段的值相对于全文本检索词相似程度的算法。
Elasticsearch 的相似度算法被定义为检索词频率/反向文档频率, TF/IDF ,包括以下内容:
检索词频率
检索词在该字段出现的频率?出现频率越高,相关性也越高。 字段中出现过 5 次要比只出现过 1 次的相关性高。
反向文档频率
每个检索词在索引中出现的频率?频率越高,相关性越低。检索词出现在多数文档中会比出现在少数文档中的权重更低。
字段长度准则
字段的长度是多少?长度越长,相关性越低。 检索词出现在一个短的 title 要比同样的词出现在一个长的 content 字段权重更大。
单个查询可以联合使用 TF/IDF 和其他方式,比如短语查询中检索词的距离或模糊查询里的检索词相似度。
相关性并不只是全文本检索的专利。也适用于 yes|no 的子句,匹配的子句越多,相关性评分越高。
如果多条查询子句被合并为一条复合查询语句,比如 bool 查询,则每个查询子句计算得出的评分会被合并到总的相关性评分中。
"_explanation":
{//1
"description":"weight(tweet:honeymoon in 0)[PerFieldSimilarity], result of:",
"value":0.076713204,
"details":[
{
"description":"fieldWeight in 0, product of:",
"value":0.076713204,
"details":[
{//2
"description":"tf(freq=1.0), with freq of:",
"value":1,
"details":[
{
"description":"termFreq=1.0",
"value":1
}
]
},
{//3
"description":"idf(docFreq=1, maxDocs=1)",
"value":0.30685282
},
{//4
"description":"fieldNorm(doc=0)",
"value":0.25
}
]
}
]
}
1、honeymoon
相关性评分计算的总结
1、检索词频率
1、反向文档频率
1、字段长度准则
ps:由于explain的使用十分的消耗性能,所以只能在调试时使用
第一部分是关于计算的总结。告诉了我们 honeymoon 在 tweet 字段中的检索词频率/反向文档频率或TF/IDF, (这里的文档 0 是一个内部的 ID,跟我们没有关系,可以忽略。)
然后它提供了权重是如何计算的细节:
检索词频率:
检索词 honeymoon
在这个文档的 tweet
字段中的出现次数。
反向文档频率:
检索词 honeymoon
在索引上所有文档的 tweet
字段中出现的次数。
字段长度准则:
在这个文档中, tweet
字段内容的长度 -- 内容越长,值越小。
复杂的查询语句解释也非常复杂,但是包含的内容与上面例子大致相同。 通过这段信息我们可以了解搜索结果是如何产生的。
DOC VALUES
当你对一个字段进行排序时,Elasticsearch 需要访问每个匹配到的文档得到相关的值。倒排索引的检索性能是非常快的,但是在字段值排序时却不是理想的结构。
在搜索的时候,我们能通过搜索关键词快速得到结果集。
当排序的时候,我们需要倒排索引里面某个字段值的集合。换句话说,我们需要 转置 倒排索引。
转置 结构在其他系统中经常被称作 列存储 。实质上,它将所有单字段的值存储在单数据列中,这使得对其进行操作是十分高效的,例如排序。
在 Elasticsearch 中,Doc Values 就是一种列式存储结构,默认情况下每个字段的 Doc Values 都是激活的,Doc Values 是在索引时创建的,当字段索引时,Elasticsearch 为了能够快速检索,会把字段的值加入倒排索引中,同时它也会存储该字段的 Doc Values。
Elasticsearch 中的 Doc Values 常被应用到以下场景
对一个字段进行排序
对一个字段进行聚合
某些过滤,比如地理位置过滤
某些与字段相关的脚本计算
因为文档值被序列化到磁盘,我们可以依靠操作系统的帮助来快速访问。当 working set 远小于节点的可用内存,系统会自动将所有的文档值保存在内存中,使得其读写十分高速; 当其远大于可用内存,操作系统会自动把 Doc Values 加载到系统的页缓存中,从而避免了 jvm 堆内存溢出异常。