《深入理解Elasticsearch(原书第2版)》——2.3 查询模板

简介:

本节书摘来自华章计算机《深入理解Elasticsearch(原书第2版)》一书中的第2章,第2.3节,作者 [美]拉斐尔·酷奇(Rafal Ku)马雷克·罗戈任斯基(Marek Rogoziski),张世武 余洪淼 商旦 译,更多章节内容可以访问云栖社区“华章计算机”公众号查看。

2.3 查询模板

在应用程序迭代的同时,它的运行环境很可能会越来越复杂。在你所处的组织中,很可能同一个应用程序的不同部分分别有专人负责,比如说,至少有一个前端工程师和一个负责数据库层的后端工程师。将应用程序划分为几个模块分别开发的方式非常便捷高效,它能够让开发人员针对程序的不同部分并行进行开发工作,而无需在开发者之间和开发小组内部时刻同步代码。当然,你正在阅读的这本书不是关于项目管理的,而是聚焦于搜索的,因此让我们回到正题上。有时候,我们可以整理出程序使用的所有查询语句交给搜索引擎工程师,让他们协助从性能和相关性两个方面对查询语句进行优化。这种做法通常是很有帮助的。在这种情况下,应用程序开发者只需要把查询传递给Elasticsearch,而不需要考虑查询语句的构造、查询DSL语法、查询结果过滤等细节知识。

2.3.1 引入查询模板

自Elasticsearch 1.1.0版本开始,我们可以自定义查询模板。让我们回到本书开头的在线书店例子中。假定我们已经确定了需要传递给Elasticsearch的查询语句的类型,不过查询结构并未最终确定,我们还需要对它进行微调和优化。通过使用查询模板,我们可以快速构建出查询的基础骨架,然后让应用程序来提供对应的参数,最终由Elasticsearch完成查询参数的替换。

假定我们有一个针对library索引的查询语句,可以返回最相关的书籍记录。在这个查询中,我们还允许用户选择是否对书籍的库存状态做筛选。在这个场景中,我们需要传入两个参数—一个查询短语和一个代表书籍库存状态的布尔变量。最初的简化示例如下:

image

代码中的QUERY和BOOLEAN是占位符,代表应用程序传递给查询的变量。显然这个查询语句对当前示例场景来说实在太简陋了,不过之前我们已经说过,这只是它的最初版本,我们马上将对它进行改进。

既然已经有了最初版本的查询语句,我们可以基于它创建第一个查询模板。对该查询语句做简单修改如下:

image
image

可以看出,原来的占位符被替换成了{{phrase}}和{{avail}}两个变量,并且添加了一个新的params片段。当Elasticsearch在解析查询语句时,遇到一个{{phrase}}变量,它将尝试从params片段中查找出名为phrase的参数,并用参数值替换掉{{phrase}}变量。通常,我们需要把参数值放到params片段中,并在query中使用形如{{var}}的标记来引用params片段中参数名为var的参数。此外,查询本身被嵌套进一个template元素中。通过这种方式,我们实现了查询的参数化。

接下来让我们使用HTTP GET请求把以下查询语句发送给地址为/library/_search/template的REST端点(注意这里不是我们通常使用的/library/_search端点)。请求命令构造如下:

image

字符串形式的查询模板

查询模板也可以以字符串的形式提供。比如,刚才的查询模板可以变成这样:
image

可见,这种形式不太适合阅读和书写,每个引号都需要被转义,换行符容易引发格式问题,因此需要避免使用。尽管如此,如果你需要使用Mustache(一个模板引擎,我们将在下一小节探讨),则必须使用这种格式(至少在Elasticsearch的1.1.0到1.4.0之间的所有版本中必须这样做)。

 本书写作时,笔者所使用的Elasticsearch相关版本中有一个关于查询模板的小陷阱。如果你提供的查询模板中有错误,被Elasticsearch检测到后,会把错误写到服务日志里,但是从API的视角来看,错误查询将被忽略,接口将返回所有文档,就好像你刚刚发送了一个match_all查询一样。记得复查你的查询模板,直到这个缺陷不再存在。

2.3.2 Mustache模板引擎

Elasticsearch使用Mustache模板引擎(参考http://mustache.github.io )来为查询模板生成可用的查询语句。如你所见,每个变量被双大括号包裹,这一点是Mustache规范要求的,是该模板引擎间接引用变量的方式。Mustache模板引擎的完整语法不在本书讨论范围内,不过我们可以在这里简单介绍一下它最具魅力的部分,包括条件表达式、循环和默认值。

 Mustache语法的详细内容请参阅http://mustache.github.io/mustache.5.html

1. 条件表达式

{{val}}表达式用来插入变量val的值。{{#val}}和{{/val}}则用来在变量val取值计算为true时把位于它们之间的变量标记替换为变量值。

我们看一下下面这个示例:
image

这个命令将返回library索引中的所有文档。不过,假如我们把limit参数的取值改为true,则再次查询后,我们将只能得到两个文档。这是因为判断条件满足了,模板内容因此被激活。

 不幸的是,似乎直到本书写作时,笔者所使用的Elasticsearch版本在处理条件表达式时仍然有些问题。比如,其中一个相关问题可以在这里看到:https://github.com/Elasticsearch/Elasticsearch/issues/8308 。我们决定保留条件表达式这一小节,以期望相关问题都能在未来得到解决。使用条件表达式可以更方便地构造查询模板。

2. 循环

循环结构定义和条件表达式一模一样,都位于{{#val}}和{{/val}}之间。如果表达式中变量取值是数组,则可以使用{{.}}标记来指代当前变量值。

例如,假定我们需要模板引擎遍历一个词项数组来生成一个词项查询,可以执行如下命令:

image

3. 默认值

默认值标记允许我们在参数未定义时给它设置默认取值。比如,给var变量设置默认值语法的代码如下:
image

举个例子,假定我们要给查询模板中的phrase参数设置默认值“crime”,可以使用如下命令:
image

这个命令将从Elasticsearch查询出所有title字段中包含front的文档。而如果我们在params片段中不指定phrase参数的值,则使用crime来代替。

2.3.3 把查询模板保存到文件

抛开之前定义模板的方式不说,我们距离把查询跟应用程序解耦还有相当长的一段路要走。我们能够做的仅仅是把查询语句参数化,而整个查询模板字符串仍然需要保存在应用程序中。幸运的是,有一种简单的方法来改变目前这种查询定义方式,它允许Elasticsearch从config/scripts 目录中动态读取查询模板。

举例来说,让我们创建一个名为bookList.mustache的文件(在config/scripts目录中)。使用如下命令:

image
image

接下来我们就可以在查询中用模板名称来使用该文件的内容了(模板名称就是模板文件名称去掉.mustache后缀)。例如,如果我们使用bookList模板,则可以使用如下命令:

image

 Elasticsearch有一个非常方便的特性:它可以无需重启就检测到模板文件的变更。当然,我们还是需要在每个负责查询的Elasticsearch节点上部署查询模板文件。从Elasticsearch 1.4.0版本开始,你可以把模板索引到一个名为.scripts的特殊索引中。更多相关信息请参考Elasticsearch的官方文档:http://www.Elasticsearch.org/guide/en/Elasticsearch/reference/current/search-template.html

相关实践学习
以电商场景为例搭建AI语义搜索应用
本实验旨在通过阿里云Elasticsearch结合阿里云搜索开发工作台AI模型服务,构建一个高效、精准的语义搜索系统,模拟电商场景,深入理解AI搜索技术原理并掌握其实现过程。
ElasticSearch 最新快速入门教程
本课程由千锋教育提供。全文搜索的需求非常大。而开源的解决办法Elasricsearch(Elastic)就是一个非常好的工具。目前是全文搜索引擎的首选。本系列教程由浅入深讲解了在CentOS7系统下如何搭建ElasticSearch,如何使用Kibana实现各种方式的搜索并详细分析了搜索的原理,最后讲解了在Java应用中如何集成ElasticSearch并实现搜索。  
相关文章
|
数据采集 JSON 数据挖掘
Elasticsearch 的DSL查询,聚合查询与多维度数据统计
Elasticsearch的DSL查询与聚合查询提供了强大的数据检索和统计分析能力。通过合理构建DSL查询,用户可以高效地搜索数据,并使用聚合查询对数据进行多维度统计分析。在实际应用中,灵活运用这些工具不仅能提高查询效率,还能为数据分析提供深入洞察。理解并掌握这些技术,将显著提升在大数据场景中的分析和处理能力。
788 20
|
测试技术 API 开发工具
ElasticSearch7.6.x 模板及滚动索引创建及注意事项
ElasticSearch7.6.x 模板及滚动索引创建及注意事项
310 8
|
存储 JSON 监控
大数据-167 ELK Elasticsearch 详细介绍 特点 分片 查询
大数据-167 ELK Elasticsearch 详细介绍 特点 分片 查询
981 4
|
JSON 自然语言处理 算法
ElasticSearch基础2——DSL查询文档,黑马旅游项目查询功能
DSL查询文档、RestClient查询文档、全文检索查询、精准查询、复合查询、地理坐标查询、分页、排序、高亮、黑马旅游案例
ElasticSearch基础2——DSL查询文档,黑马旅游项目查询功能
|
自然语言处理 Java 关系型数据库
ElasticSearch 实现分词全文检索 - 聚合查询 cardinality
ElasticSearch 实现分词全文检索 - 聚合查询 cardinality
537 1
|
自然语言处理 搜索推荐 Java
SpringBoot 搜索引擎 海量数据 Elasticsearch-7 es上手指南 毫秒级查询 包括 版本选型、操作内容、结果截图(一)
SpringBoot 搜索引擎 海量数据 Elasticsearch-7 es上手指南 毫秒级查询 包括 版本选型、操作内容、结果截图
425 0
|
存储 自然语言处理 搜索推荐
SpringBoot 搜索引擎 海量数据 Elasticsearch-7 es上手指南 毫秒级查询 包括 版本选型、操作内容、结果截图(二)
SpringBoot 搜索引擎 海量数据 Elasticsearch-7 es上手指南 毫秒级查询 包括 版本选型、操作内容、结果截图(二)
407 0
|
存储 自然语言处理 Java
ElasticSearch 实现分词全文检索 - 经纬度定位商家距离查询
ElasticSearch 实现分词全文检索 - 经纬度定位商家距离查询
393 0
|
自然语言处理 Java
ElasticSearch 实现分词全文检索 - 高亮查询
ElasticSearch 实现分词全文检索 - 高亮查询
300 0
|
缓存 自然语言处理 Java
ElasticSearch 实现分词全文检索 - filter查询
ElasticSearch 实现分词全文检索 - filter查询
231 0