《深入理解ElasticSearch》——2.2 查询改写

本文涉及的产品
检索分析服务 Elasticsearch 版,2核4GB开发者规格 1个月
简介:

本节书摘来自华章计算机《深入理解ElasticSearch》一书中的第2章,第2.2节,作者:[美] 拉斐尔·酷奇(Rafa Ku) 马雷克·罗戈任斯基(Marek Rogoziński)更多章节内容可以访问云栖社区“华章计算机”公众号查看。

2.2 查询改写

如果你之前使用过诸如前缀查询或通配符查询之类的查询类型,那么你会发现这些都是基于多词项的查询,且都涉及查询改写。ElasticSearch(实际上是Lucene执行该操作)使用查询改写是出于对性能的考虑。从Lucene的角度来看,所谓的查询改写操作,就是把费时的原始查询类型实例改写成一个性能更高的查询类型实例。
2.2.1 前缀查询范例
演示查询改写过程的最好方式莫过于通过范例深入了解该过程的内部实现机制,尤其是要了解原始查询中的词项是如何改写成目标查询中那些词项的。假设索引了下面这些文档中的数据:


935e5719fafc94526bbe7bbb52cc03c0c18bd13b

也许用户想找出索引中所有name字段以字母j开头的文档。简单起见,我们在clients索引中执行以下查询:


7868fc5f1c19a74c78788715272e3ac2b1abebb3

这里使用了一个简单的前缀查询,想检索出所有name字段以字母j开头的文档。我们同时也设置了查询改写属性以确定执行查询改写的具体方法,不过现在先跳过该参数,具体的参数值将在本章的后续部分讨论。
执行前面的查询,将得到以下结果:


b21dea2b7594ddfee3731da2b473bd4a97eb4b29

如你所见,返回结果中有3个文档,这些文档的name字段以字母j开头。我们并没有显式设置待查询索引的映射,因此ElasticSearch猜测name字段的映射,并将其设置为字符串类型并进行文本分析。可使用下面的命令:


image
" >

2.2.2 回顾Apache Lucene
现在回顾一下Lucene。如果你还记得Lucene倒排索引是如何构建的,就知道倒排索引中包含了词项,词频以及文档指针(如果忘了,请重新阅读1.1节)。我们看看之前存储到clients索引中的数据是如何组织的:


<a href=https://yqfile.alicdn.com/3bd2a3d8d116205562f2bd1f79867b72a7cd15bf.png" >

Term这一列非常重要。如果去探究ElasticSearch和Lucene的内部实现,就会发现前缀查询已经改写为下面这种查询:

<a href=https://yqfile.alicdn.com/f8fd007eb0d76417f46f65dce5ec58d4ec885930.png" >

这意味着我们的前缀查询已经改写为常数得分查询(constant score query),该查询由一个布尔查询构成,而这个布尔查询又由三个词项查询构成。Lucene所做的事情就是:枚举索引中的词项,并利用这些词项的信息来构建新的查询。当我们比较改写前后的两个查询的执行效果,会发现改写后的查询性能有所提升,尤其是当索引中有大量不同词项时。
如果想手动构建这个改写后的查询,可执行类似下面的代码(本范例代码存储在constant_score_query.json文件中):


d3f4ffe17536d4e69fc15ac2596c6a32fe78c2c3

现在,让我们看看有哪些可以配置的查询改写属性。
2.2.3 查询改写的属性
之前已经说过可以对任何多词项查询(如ElasticSearch中的前缀和通配符查询)使用rewrite参数来控制查询改写。我们可以将rewrite参数存放在代表实际查询的JSON对象中,例如,下面的代码:


<a href=https://yqfile.alicdn.com/5041d7c8865ca2ea31453d177677191a1c046835.png" >

现在我们来看看rewrite参数有哪些选项可以配置:

  • scoring_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的Javadoc描述的那样,该选项按如下方式改写原始查询:通过顺序遍历每个词项来创建一个私有的过滤器,标记跟每个词项相关的所有文档。命中的文档被赋予一个跟查询权重相同的常量得分。当命中词项数或文档数较大时,该方法比scoring_boolean 和constant_score_boolean执行速度更快。
  • top_terms_N:该选项将每个生成的词项转化为布尔查询中的一个或从句,并保存计算出来的查询得分。与scoring_boolean不同之处在于,该方法只保留了最佳的前N个词项,从而避免超出布尔从句数的限制。
  • top_terms_boost_N:该选项与top_terms_N类似,不同之处在于该选项产生的从句类型为常量得分查询,得分为从句的权重。
  • 当rewrite属性设置为constant_score_auto或者根本不设置时,constant_score_filter或constant_score_boolean属性的取值依赖于查询类型及其构造方式。

现在,让我们再看一个例子。如果想在范例查询中使用top_terms_N选项,并且N的值设置为10,那么查询看起来与下面的代码类似:


2b00101b05b9cf9b5e142dbfdac714fcb946dae8

结束本节之前,读者应该会产生一个疑问,即如何决定何时采用何种查询改写方法?该问题的答案更多取决于具体的应用场景。简单来说,如果你能接受低精度(往往伴随着高性能),那么可以采用top N查询改写方法。如果你需要更高的查询精度(往往伴随着低性能),那么应该使用布尔方法。

相关实践学习
使用阿里云Elasticsearch体验信息检索加速
通过创建登录阿里云Elasticsearch集群,使用DataWorks将MySQL数据同步至Elasticsearch,体验多条件检索效果,简单展示数据同步和信息检索加速的过程和操作。
ElasticSearch 入门精讲
ElasticSearch是一个开源的、基于Lucene的、分布式、高扩展、高实时的搜索与数据分析引擎。根据DB-Engines的排名显示,Elasticsearch是最受欢迎的企业搜索引擎,其次是Apache Solr(也是基于Lucene)。 ElasticSearch的实现原理主要分为以下几个步骤: 用户将数据提交到Elastic Search 数据库中 通过分词控制器去将对应的语句分词,将其权重和分词结果一并存入数据 当用户搜索数据时候,再根据权重将结果排名、打分 将返回结果呈现给用户 Elasticsearch可以用于搜索各种文档。它提供可扩展的搜索,具有接近实时的搜索,并支持多租户。
相关文章
|
2月前
|
存储 固态存储 Java
Elasticsearch中查询性能优化
Elasticsearch中查询性能优化
185 0
|
3月前
Elasticsearch之RestClient查询文档
Elasticsearch之RestClient查询文档
138 1
|
2月前
|
缓存 算法 索引
【Elasticsearch专栏 07】深入探索:Elasticsearch的倒排索引如何进行模糊查询和通配符查询
Elasticsearch的倒排索引支持模糊查询和通配符查询,通过特定的算法和数据结构,能够实现对关键词的模糊匹配和通配符匹配。这两种查询类型提供了更灵活的搜索功能,但可能影响查询性能,需结合优化策略使用。
|
2月前
|
缓存 自然语言处理 数据挖掘
一篇文章让你学会Elasticsearch中的查询
一篇文章让你学会Elasticsearch中的查询
137300 118
|
2月前
|
测试技术 定位技术 API
万字长文:一文彻底搞懂Elasticsearch中Geo数据类型查询、聚合、排序
万字长文:一文彻底搞懂Elasticsearch中Geo数据类型查询、聚合、排序
94607 140
|
2月前
|
JSON 前端开发 API
【Elasticsearch】搜索结果处理和RestClient查询文档
【Elasticsearch】搜索结果处理和RestClient查询文档
330 0
|
2月前
|
JSON 自然语言处理 算法
【Elasticsearch】DSL查询文档
【Elasticsearch】DSL查询文档
312 0
|
3月前
|
Java
Springboot整合Elasticsearch 7.X 复杂查询
这里使用Springboot 2.7.12版本,Elasticsearch为7.15.0。
Springboot整合Elasticsearch 7.X 复杂查询
|
3月前
|
Java
elasticsearch在Java中查询指定列的方法
elasticsearch在Java中查询指定列的方法
84 0
|
3月前
|
Java
SpringBoot中进行elasticSearch查询,使用QueryBuilders构建各类条件查询
SpringBoot中进行elasticSearch查询,使用QueryBuilders构建各类条件查询
60 0