本节书摘来华章计算机《深入理解Elasticsearch(原书第2版)》一书中的第2章 ,第2.2.3节,[美]拉斐尔·酷奇(Rafal Ku) 马雷克·罗戈任斯基(Marek Rogoziski)著 张世武 余洪淼 商旦 译 更多章节内容可以访问云栖社区“华章计算机”公众号查看。
2.2.3 查询改写的属性
当然,多词项查询的rewrite属性也可以支持除了“constant_score_boolean”之外的其他取值。我们可以通过这个属性来控制查询在Lucene内部的改写方式。我们可以将rewrite参数存放在代表实际查询的JSON对象中,例如,像下面的代码这样:
现在让我们来看看rewrite参数有哪些选项可以配置。
scoring_boolean:该选项将每个生成的词项转化为布尔查询中的一个或从句(Boolean should clause)。这种改写方法需要针对每个文档都计算得分。因此,这种方法比较耗费CPU(因为要计算和保存每个词项的得分),而且有些查询生成了太多的词项,以至于超出了布尔查询默认的1024个从句的限制。默认的布尔查询限制可以通过设置Elasticsearch.yml文件的index.query.bool.max_clause_count属性来修改。用户需谨记,改写后的布尔查询的从句数越多,查询性能越低。
constant_score_boolean:该选项与前面提到过的scoring_boolean类似,但是CPU耗费更少,这是因为并不计算每个从句的得分,而是每个从句得到一个与查询权重相同的一个常数得分,默认情况下等于1,我们也可以通过设置查询权重来改变这个默认值。与scoring_boolean类似,该选项也有布尔从句数的限制。
constant_score_filter:正如Lucene的Javadocs描述的那样,该选项按如下方式改写原始查询—通过顺序遍历每个词项来创建一个私有的过滤器,标记所有包含这个词项的文档。命中的文档被赋予一个与查询权重相同的常量得分。当命中词项数或文档数较大时,该方法比scoring_boolean 和constant_score_boolean执行速度更快。
top_terms_N:该选项将每个生成的词项转化为布尔查询中的一个或从句,并保存计算出来的查询得分。与scoring_boolean不同之处在于,该方法只保留最佳的N个词项,以避免触及布尔从句数的限制,并提升查询整体性能。
top_terms_boost_N:该选项与top_terms_N类似,不同之处在于它的文档得分不是通过计算得出的,而是被设置为跟查询权重(boost)一致,默认值为1。
当rewrite属性设置为constant_score_auto或者没有设置时,Elasticsearch会根据查询的类型及其构造方式来决定是使用constant_score_filter还是constant_score_boolean。
现在,让我们再看一个例子。如果我们想在范例查询中使用top_terms_N选项,并且N的值设置为2,那么查询看起来与下面的代码类似:
从Elasticsearch返回的结果中可以看出,和我们之前使用的查询不同,这里的文档得分都不等于1.0。
这是因为top_terms_N需要保留得分最高的N个词项。
结束本节之前,读者应该会产生一个疑问,我们如何决定何时采用何种查询改写方法?该问题的答案更多地取决于您的应用场景。简单来说,如果您能接受较低的精度和相关性(但是追求更高的性能),那么可以采用top-N查询改写方法。如果您需要更高的查询精度和更好的相关性(同时可以接受较低的性能),那么应该采用布尔方法。