2019独角兽企业重金招聘Python工程师标准>>>
Elasticsearch 的相似度算法 被定义为检索词频率/反向文档频率, TF/IDF ,包括以下内容:
-
检索词频率
检索词在该字段出现的频率?出现频率越高,相关性也越高。 字段中出现过 5 次要比只出现过 1 次的相关性高。
-
反向文档频率
每个检索词在索引中出现的频率?频率越高,相关性越低。检索词出现在多数文档中会比出现在少数文档中的权重更低。
-
字段长度准则
字段的长度是多少?长度越长,相关性越低。 检索词出现在一个短的 title 要比同样的词出现在一个长的 content 字段权重更大。
++词频率和 文档频率是在每个分片中计算出来的,而不是每个索引中++。 可以在查询中将explain
设为true,可以得到详细的评分过程。此操作是十分昂贵的,它只能用作调试工具 。千万不要用于生产环境。
GET /employee/doc/_search?format=yaml
{"explain": true,...
}
Elasticsearch 中的 ==Doc Values== 常被应用到以下场景:
- 对一个字段进行排序
- 对一个字段进行聚合
- 某些过滤,比如地理位置过滤
- 某些与字段相关的脚本计算
排序发生在索引时建立的平行数据结构中。
组合查询对相关性影响
在一个查询中使用组合查询(如bool),它除了决定一个文档是否应该被包括在结果中,还会计算文档的相关程度。
GET /my_index/my_type/_search
{"query": {"bool": {"must": { "match": { "title": "quick" }},"must_not": { "match": { "title": "lazy" }},"should": [{ "match": { "title": "brown" }},{ "match": { "title": "dog" }}]}}
}
两个should语句,一个文档不必包含 brown 或 dog这两个词项,但如果一旦包含,我们就认为它们更相关。
bool 查询会为每个文档计算相关度评分 _score , 再将所有匹配的 must 和 should 语句的分数 _score 求和,最后除以 must 和 should 语句的总数。
must_not 语句不会影响评分; 它的作用只是将不相关的文档排除。
所有 must 语句必须匹配,所有 must_not 语句都必须不匹配,但有多少 should 语句应该匹配呢? 默认情况下,没有 should 语句是必须匹配的,只有一个例外:那就是当没有 must 语句的时候,至少有一个 should 语句必须匹配。
通过指定 boost 来控制任何查询语句的相对的权重, boost 的默认值为 1 ,大于 1 会提升一个语句的相对权重。
可以通过指定 boost 来控制任何查询语句的相对的权重, boost 的默认值为 1 ,大于 1 会提升一个语句的相对权重。但是这种提升或降低并不是线性的,换句话说,如果一个 boost 值为 2 ,并不能获得两倍的评分 _score 。
boost 值比较合理的区间处于 1 到 10 之间,当然也有可能是 15 。如果为 boost 指定比这更高的值,将不会对最终的评分结果产生更大影响,因为评分是被 归一化的(normalized) 。
GET /_search
{"query": {"bool": {"must": {"match": { "content": {"query": "full text search","operator": "and"}}},"should": [{ "match": {"content": {"query": "Elasticsearch","boost": 3 }}},{ "match": {"content": {"query": "Lucene","boost": 2 }}}]}}
}
不同层级对评分的影响
GET /_search
{"query": {"bool": {"should": [{ "match": { "title": "War and Peace" }},{ "match": { "author": "Leo Tolstoy" }},{ "bool": {"should": [{ "match": { "translator": "Constance Garnett" }},{ "match": { "translator": "Louise Maude" }}]}}]}}
}
bool 查询运行每个 match 查询,再把评分加在一起,然后将结果与所有匹配的语句数量相乘,最后除以所有的语句数量。处于同一层的每条语句具有相同的权重。在前面这个例子中,包含 translator 语句的 bool 查询,只占总评分的三分之一。如果将 translator 语句与 title 和 author 两条语句放入同一层,那么 title 和 author 语句只贡献四分之一评分。
dis_max查询
分离最大化查询(Disjunction Max Query)指的是: 将任何与任一查询匹配的文档作为结果返回,但只将最佳匹配的评分作为查询的评分结果返回。
tie_breaker参数
{"query": {"dis_max": {"queries": [{ "match": { "title": "Quick pets" }},{ "match": { "body": "Quick pets" }}],"tie_breaker": 0.3}}
}
tie_breaker 参数提供了一种 dis_max 和 bool 之间的折中选择,它的评分方式如下:
- 获得最佳匹配语句的评分 _score 。
- 将其他匹配语句的评分结果与 tie_breaker 相乘。
- 对以上评分求和并规范化。
tie_breaker 可以是 0 到 1 之间的浮点数,其中 0 代表使用 dis_max 最佳匹配语句的普通逻辑, 1 表示所有匹配语句同等重要。最佳的精确值需要根据数据与查询调试得出,但是合理值应该与零接近(处于 0.1 - 0.4 之间),这样就不会颠覆 dis_max 最佳匹配性质的根本。
提升单个字段的权重
可以使用 ^ 字符语法为单个字段提升权重,在字段名称的末尾添加 ^boost , 其中 boost 是一个浮点数
{"multi_match": {"query": "Quick brown fox","fields": [ "*_title", "chapter_title^2" ] }
}
chapter_title 这个字段的 boost 值为 2 ,而其他两个字段 book_title 和 section_title 字段的默认 boost 值为 1 。