本文共 2555 字,大约阅读时间需要 8 分钟。
本节书摘来自华章计算机《深入理解ElasticSearch》一书中的第2章,第2.2节,作者:[美] 拉斐尔·酷奇(Rafa Ku) 马雷克·罗戈任斯基(Marek Rogoziński)更多章节内容可以访问云栖社区“华章计算机”公众号查看。
如果你之前使用过诸如前缀查询或通配符查询之类的查询类型,那么你会发现这些都是基于多词项的查询,且都涉及查询改写。ElasticSearch(实际上是Lucene执行该操作)使用查询改写是出于对性能的考虑。从Lucene的角度来看,所谓的查询改写操作,就是把费时的原始查询类型实例改写成一个性能更高的查询类型实例。
2.2.1 前缀查询范例演示查询改写过程的最好方式莫过于通过范例深入了解该过程的内部实现机制,尤其是要了解原始查询中的词项是如何改写成目标查询中那些词项的。假设索引了下面这些文档中的数据:也许用户想找出索引中所有name字段以字母j开头的文档。简单起见,我们在clients索引中执行以下查询:
这里使用了一个简单的前缀查询,想检索出所有name字段以字母j开头的文档。我们同时也设置了查询改写属性以确定执行查询改写的具体方法,不过现在先跳过该参数,具体的参数值将在本章的后续部分讨论。
执行前面的查询,将得到以下结果:如你所见,返回结果中有3个文档,这些文档的name字段以字母j开头。我们并没有显式设置待查询索引的映射,因此ElasticSearch猜测name字段的映射,并将其设置为字符串类型并进行文本分析。可使用下面的命令:
2.2.2 回顾Apache Lucene
现在回顾一下Lucene。如果你还记得Lucene倒排索引是如何构建的,就知道倒排索引中包含了词项,词频以及文档指针(如果忘了,请重新阅读1.1节)。我们看看之前存储到clients索引中的数据是如何组织的:这意味着我们的前缀查询已经改写为常数得分查询(constant score query),该查询由一个布尔查询构成,而这个布尔查询又由三个词项查询构成。Lucene所做的事情就是:枚举索引中的词项,并利用这些词项的信息来构建新的查询。当我们比较改写前后的两个查询的执行效果,会发现改写后的查询性能有所提升,尤其是当索引中有大量不同词项时。
如果想手动构建这个改写后的查询,可执行类似下面的代码(本范例代码存储在constant_score_query.json文件中):现在,让我们看看有哪些可以配置的查询改写属性。
2.2.3 查询改写的属性之前已经说过可以对任何多词项查询(如ElasticSearch中的前缀和通配符查询)使用rewrite参数来控制查询改写。我们可以将rewrite参数存放在代表实际查询的JSON对象中,例如,下面的代码:现在我们来看看rewrite参数有哪些选项可以配置:
现在,让我们再看一个例子。如果想在范例查询中使用top_terms_N选项,并且N的值设置为10,那么查询看起来与下面的代码类似:
结束本节之前,读者应该会产生一个疑问,即如何决定何时采用何种查询改写方法?该问题的答案更多取决于具体的应用场景。简单来说,如果你能接受低精度(往往伴随着高性能),那么可以采用top N查询改写方法。如果你需要更高的查询精度(往往伴随着低性能),那么应该使用布尔方法。
转载地址:http://iyzso.baihongyu.com/