本节书摘来自华章计算机《深入理解ElasticSearch》一书中的第2章,第2.1节,作者:[美] 拉斐尔·酷奇(Rafa Ku) 马雷克·罗戈任斯基(Marek Rogoziński)更多章节内容可以访问云栖社区“华章计算机”公众号查看。
第2章 查询DSL进阶
上一章我们了解了什么是Apache Lucene,它的整体架构,以及文本分析过程是如何完成的。之后,我们介绍了Lucene的查询语言及其用法。除此之外,我们还讨论了ElasticSearch及其架构和一些核心 概念。在本章,我们将深入研究ElasticSearch的查询DSL(Domain Specific Language)。然而,在了解那些高级查询之前,我们先来了解Lucene评分公式的工作原理。本章将涵盖以下内容:
- Lucene默认评分公式是如何工作的。
- 什么是查询重写。
- 查询二次评分是如何工作的。
- 如何在单次请求中实现批量准实时读取操作。
- 如何在单次请求中发送多个查询。
- 如何对包括嵌套文档和多值字段的数据排序。
- 如何更新已索引的文档。
- 如何通过使用过滤器来优化查询。
- 如何在ElasticSearch的切面计算机制中使用过滤器和作用域。
2.1 Apache Lucene默认评分公式解释
对于查询相关性,重点是去理解文档对查询的得分是如何计算出来的。什么是文档得分?它是一个刻画文档与查询匹配程度的参数。本节我们就将了解Apache Lucene的默认评分机制:TF/IDF(词频/逆文档频率)算法以及它是如何影响文档召回的。了解评分公式的工作原理对构造复杂查询以及分析查询中因子的重要性都是很有价值的。
2.1.1 何时文档被匹配上
当一个文档经Lucene返回,则意味着该文档与用户提交的查询是匹配的。在这种情况下,每个返回的文档都有一个得分。得分越高,文档相关度更高,至少从Apache Lucene及其评分公式的角度来看是这样的。显而易见,同一个文档针对不同查询的得分是不同的,而且比较某文档在不同查询中的得分是没有意义的。读者需要注意,同一文档在不同查询中的得分不具备可比较性,不同查询返回文档中的最高得分也不具备可比较性。这是因为文档得分依赖多个因子,除了权重和查询本身的结构,还包括匹配的词项数目,词项所在字段,以及用于查询规范化的匹配类型等。在一些比较极端的情况下,同一个文档在相似查询中的得分非常悬殊,仅仅是因为使用了自定义得分查询或者命中词项数发生了急剧变化。
现在,让我们再回到评分过程。为了计算文档得分,需要考虑以下这些因子:
- 文档权重(document boost):索引期赋予某个文档的权重值。
-字段权重(field boost):查询期赋予某个字段的权重值。 - 协调因子(coord):基于文档中词项命中个数的协调因子,一个文档命中了查询中的词项越多,得分越高。
- 逆文档频率(inverse document frequency):一个基于词项的因子,用来告诉评分公式该词项有多么罕见。逆文档频率越低,词项越罕见。评分公式利用该因子为包含罕见词项的文档加权。
- 长度范数(length norm):每个字段的基于词项个数的归一化因子(在索引期计算出来并存储在索引中)。一个字段包含的词项数越多,该因子的权重越低,这意味着Apache Lucene评分公式更“喜欢”包含更少词项的字段。
词频(term frequency):一个基于词项的因子,用来表示一个词项在某个文档中出现了多少次。词频越高,文档得分越高。 - 查询范数(query norm):一个基于查询的归一化因子,它等于查询中词项的权重平方和。查询范数使不同查询的得分能相互比较,尽管这种比较通常是困难且不可行的。
2.1.2 TF/IDF评分公式
现在我们来看评分公式。请记住,为了调节查询相关性,你并不需要深入理解这个公式的来龙去脉,但是了解它的工作原理是非常重要的。
Lucene理论评分公式
TF/IDF公式的理论形式如下:
score(q, d) = coord(q, d)*queryBoost(q)**lengthNorm(d)*docBoost(d)
上面的公式糅合了布尔检索模型和向量空间检索模型。现在,我们并不讨论理论评分公式,而是直接跳到Lucene实际评分公式,因为在Lucene内部就是这么实现并使用的。
Lucene实际评分公式
现在让我们看看Lucene实际使用的评分公式:
score(q, d) = coord(q, d)*queryNorm(q)*(tf(t in d)*idf(t)2*boost(t)*norm(t, d))
也许你已经看到了,得分公式是一个关于查询q和文档d的函数,有两个因子coord和queryNorm并不直接依赖查询词项,而是与查询词项的一个求和公式相乘。
求和公式中每个加数由以下因子连乘所得:词频、逆文档频率、词项权重、范数。范数就是之前提到的长度范数。
这个公式听起来很复杂。请别担心,你并不用记住所有的细节,而只需意识到哪些因素是跟评分有关即可。从前面的公式我们可以导出一些基本规则:
越多罕见的词项被匹配上,文档得分越高。
文档字段越短(包含更少的词项),文档得分越高。
权重越高(不论是索引期还是查询期赋予的权重值),文档得分越高。
正如你所见,Lucene将最高得分赋予同时满足以下条件的文档:包含多个罕见词项,词项所在字段较短(该字段索引了较少的词项)。该公式更“喜欢”包含罕见词项的文档。
2.1.3 ElasticSearch如何看评分
总而言之,是ElasticSearch使用了Lucene的评分功能,但好在我们可以替换默认的评分算法(更多细节请参考3.1节)。还有一点请记住,ElasticSearch使用了Lucene的评分功能但不仅限于Lucene的评分功能。用户可以使用各种不同的查询类型以精确控制文档评分的计算(如custom_boost_factor查询、constant_score查询、custom_score查询等),还可以通过使用脚本(scripting)来改变文档得分,还可以使用ElasticSearch 0.90中出现的二次评分功能,通过在返回文档集之上执行另外一个查询,重新计算前N个文档的文档得分。