我们发现一些用户经常编写了一些非常冗长和复杂的查询 - 在很多情况下,相同的查询会一遍又一遍地执行,但是会有一些不同的值作为参数来查询。在这种情况下,我们觉得使用一个search template(搜索模板)来做这样的工作非常合适。搜索模板允许您使用可在执行时定义的参数定义查询。

Search template的好处是:

  • 避免在多个地方重复代码
  • 更容易测试和执行您的查询
  • 在应用程序间共享查询
  • 允许用户只执行一些预定义的查询
  • 将搜索逻辑与应用程序逻辑分离

定义一个Search template

首先,我们来定义一个search template来看看它到底是什么东西。使用_scripts端点将模板存储在集群状态中。在search template中使用的语言叫做mustache。(http://mustache.github.io/mustache.5.html)

    POST _scripts/my_search_template
{
"script": {
"lang": "mustache",
"source": {
"query": {
"match": {
"{{my_field}}": "{{my_value}}"
}
}
}
}
}

在这里,我们定义了一个叫做my_search_template的search template。如果我们想更新这个search template,我们可以直接进行修改,然后再次运行上面的命令即可。

在match的字段里,我们定义了两个参数:my_field及my_value。下面,我们来首先建立一个叫做twitter的数据库:

    PUT twitter/_doc/1
{
"user" : "双榆树-张三",
"message" : "今儿天气不错啊,出去转转去",
"uid" : 2,
"age" : 20,
"city" : "北京",
"province" : "北京",
"country" : "中国",
"address" : "中国北京市海淀区",
"location" : {
"lat" : "39.970718",
"lon" : "116.325747"
}
} PUT twitter/_doc/2
{
"user" : "虹桥-老吴",
"message" : "好友来了都今天我生日,好友来了,什么 birthday happy 就成!",
"uid" : 7,
"age" : 90,
"city" : "上海",
"province" : "上海",
"country" : "中国",
"address" : "中国上海市闵行区",
"location" : {
"lat" : "31.175927",
"lon" : "121.383328"
}
}

我们这里把上面的两个文档存于到twitter的index之中。我们现在可以使用我们刚才定义的search template来进行搜索:

    GET twitter/_search/template
{
"id": "my_search_template",
"params": {
"my_field": "city",
"my_value": "北京"
}
}

显示的结果是:

    {
"took" : 1,
"timed_out" : false,
"_shards" : {
"total" : 1,
"successful" : 1,
"skipped" : 0,
"failed" : 0
},
"hits" : {
"total" : {
"value" : 1,
"relation" : "eq"
},
"max_score" : 0.9808292,
"hits" : [
{
"_index" : "twitter",
"_type" : "_doc",
"_id" : "1",
"_score" : 0.9808292,
"_source" : {
"user" : "双榆树-张三",
"message" : "今儿天气不错啊,出去转转去",
"uid" : 2,
"age" : 20,
"city" : "北京",
"province" : "北京",
"country" : "中国",
"address" : "中国北京市海淀区",
"location" : {
"lat" : "39.970718",
"lon" : "116.325747"
}
}
}
]
}
}

显示它只显示了我们的city为北京的一个文档,另外一个上海的文档没有做任何的显示。说明我们定义的search template是工作的。

条件判断

在Mustache语言中,它没有if/else这样的判断,但是你可以定section来跳过它如果那个变量是false还是没有被定义:

    {{#param1}}
"This section is skipped if param1 is null or false"
{{/param1}}

我们定义如下的一个search template:

    POST _scripts/docs_from_beijing_and_age
{
"script": {
"lang": "mustache",
"source":
"""
{
"query": {
"bool": {
"must": [
{
"match": {
"city": "{{search_term}}"
}
}
{{#search_age}}
,
{
"range": {
"age": {
"gte": {{search_age}}
}
}
}
{{/search_age}}
]
}
}
}
"""
}
}

在这里,我们同时定义了两个变量:search_term及search_age。针对search_age,我们做了一个判断,如果它有定义,及做一个range的查询。如果没有定义,就只用search_term。那么我们来做如下的实验:

    GET twitter/_search/template
{
"id": "docs_from_beijing_and_age",
"params": {
"search_term": "北京"
}
}

显示的结果是:

    {
"took" : 0,
"timed_out" : false,
"_shards" : {
"total" : 1,
"successful" : 1,
"skipped" : 0,
"failed" : 0
},
"hits" : {
"total" : {
"value" : 1,
"relation" : "eq"
},
"max_score" : 0.9808292,
"hits" : [
{
"_index" : "twitter",
"_type" : "_doc",
"_id" : "1",
"_score" : 0.9808292,
"_source" : {
"user" : "双榆树-张三",
"message" : "今儿天气不错啊,出去转转去",
"uid" : 2,
"age" : 20,
"city" : "北京",
"province" : "北京",
"country" : "中国",
"address" : "中国北京市海淀区",
"location" : {
"lat" : "39.970718",
"lon" : "116.325747"
}
}
}
]
}
}

显然,city为北京的文档已经被搜索到了。如果我们做如下的查询:

    GET twitter/_search/template
{
"id": "docs_from_beijing_and_age",
"params": {
"search_term": "北京",
"search_age": "30"
}
}

我们将搜索不到任何的结果,这是因为在这次查询中search_age已经被启用,而且在数据库中没有一个文档是来自“北京”,并且年龄大于30的。我们可以做如下的查询:

    GET twitter/_search/template
{
"id": "docs_from_beijing_and_age",
"params": {
"search_term": "北京",
"search_age": "20"
}
}

那么这次的显示结果为:

    {
"took" : 0,
"timed_out" : false,
"_shards" : {
"total" : 1,
"successful" : 1,
"skipped" : 0,
"failed" : 0
},
"hits" : {
"total" : {
"value" : 1,
"relation" : "eq"
},
"max_score" : 1.9808292,
"hits" : [
{
"_index" : "twitter",
"_type" : "_doc",
"_id" : "1",
"_score" : 1.9808292,
"_source" : {
"user" : "双榆树-张三",
"message" : "今儿天气不错啊,出去转转去",
"uid" : 2,
"age" : 20,
"city" : "北京",
"province" : "北京",
"country" : "中国",
"address" : "中国北京市海淀区",
"location" : {
"lat" : "39.970718",
"lon" : "116.325747"
}
}
}
]
}
}

显然这次我们搜索到我们想要的结果。

查询search template

GET _scripts/<templateid>

针对我们的情况:

GET _scripts/docs_from_beijing_and_age

显示的结果为:

    {
"_id" : "docs_from_beijing_and_age",
"found" : true,
"script" : {
"lang" : "mustache",
"source" : """
{
"query": {
"bool": {
"must": [
{
"match": {
"city": "{{search_term}}"
}
}
{{#search_age}}
,
{
"range": {
"age": {
"gte": {{search_age}}
}
}
}
{{/search_age}}
]
}
}
}
"""
}
}

这个正是我们之前定义的一个search template。

删除一个search template

我们可以通过如下的命令来删除一个已经创建的search template:

DELETE _scripts/<templateid>

验证search template

我们可以通过_render端点来验证我们的search template。比如:

    GET _render/template
{
"source": """
{
"query": {
"bool": {
"must": [
{
"match": {
"city": "{{search_term}}"
}
}
{{#search_age}}
,
{
"range": {
"age": {
"gte": {{search_age}}
}
}
}
{{/search_age}}
]
}
}
}
""",
"params": {
"search_term": "北京",
"search_age": "20"
}
}

那么显示的结果是:

    {
"template_output" : {
"query" : {
"bool" : {
"must" : [
{
"match" : {
"city" : "北京"
}
},
{
"range" : {
"age" : {
"gte" : 20
}
}
}
]
}
}
}
}

显然,这个就是我们想要的结果。

参考:

【1】https://www.elastic.co/guide/en/elasticsearch/reference/7.4/search-template.html

Elasticsearch:search template的更多相关文章

  1. Elasticsearch:跨集群搜索 Cross-cluster search (CCS)

    转载自:https://blog.csdn.net/UbuntuTouch/article/details/104588232 跨集群搜索(cross-cluster search)使您可以针对一个或 ...

  2. elasticsearch.net search入门使用指南中文版(翻译)

    elasticsearch.net search入门使用指南中文版,elasticsearch.Net是一个非常底层且灵活的客户端,它不在意你如何的构建自己的请求和响应.它非常抽象,因此所有的elas ...

  3. elasticsearch.net search入门使用指南中文版

    原文:http://edu.dmeiyang.com/book/nestusing.html elasticsearch.net为什么会有两个客户端? Elasticsearch.Net是一个非常底层 ...

  4. Elasticsearch URI search 查询语法整理

    Elasticsearch URI search 一.请求体查询与空查询 1. 请求体查询(request body search) 简单查询语句(lite)是一种有效的命令行adhoc查询.但是,如 ...

  5. Elasticsearch:Index生命周期管理入门

    如果您要处理时间序列数据,则不想将所有内容连续转储到单个索引中. 取而代之的是,您可以定期将数据滚动到新索引,以防止数据过大而又缓慢又昂贵. 随着索引的老化和查询频率的降低,您可能会将其转移到价格较低 ...

  6. Go标准库:Go template用法详解

    本文只介绍template的语法和用法,关于template包的函数.方法.template的结构和原理,见:深入剖析Go template. 入门示例 以下为test.html文件的内容,里面使用了 ...

  7. Python:Day53 Template基础

    一.模板由 html代码+逻辑控制代码 组成 二.逻辑控制代码的组成 1.变量(使用双大括号来引用变量) 语法格式:{{ var_name }} -----------------------Temp ...

  8. Django学习笔记(二):使用Template让HTML、CSS参与网页建立

    Django学习笔记(二):使用Template让HTML.CSS参与网页建立 通过本文章实现: 了解Django中Template的使用 让HTML.CSS等参与网页建立 利用静态文件应用网页样式 ...

  9. vue报错:Component template should contain exactly one root element. If you are using v-if on multiple elements, use v-else-if to chain them instead.

    在.vue文件中引入了 element-ui 的 table 和 pagination 组件后,报错:Component template should contain exactly one roo ...

随机推荐

  1. 环境变量配置文件profile

    环境变量配置文件 在Ubuntu中有如下几个文件可以设置环境变量1./etc/profile:在登录时,操作系统定制用户环境时使用的第一个文件,此文件为系统的每个用户设置环境信息,当用户第一次登录时, ...

  2. oracle索引2

    问什么问题? 索引有什么代价?哪些场景下你需要建索引?或者有时候反过来问,哪些场景下不推荐建索引. 建好索引之后,怎么才能最高效地利用索引?或者反过来问,请说出一个无法有效利用已建索引的案例. 索引的 ...

  3. 将mysql中一行中的几个字段 转换成一列并从其他数据库中查对应的邮件信息

    --将项目中的总监,经理,等的邮箱合并为一行 SELECT GROUP_CONCAT(t.USER_EMAIL SEPARATOR ' ') mail_address FROM portal.t_ac ...

  4. 什么是阿里云SCDN

    简介 SCDN(Secure Content Delivery Network),即拥有安全防护能力的CDN服务,提供稳定加速的同时,智能预判攻击行为,通过智能的调度系统将DDoS攻击请求切换至高防I ...

  5. 盒模型中padding、border、margin的区别

    在CSS中,规定了一种基本设计模型——盒模型(也叫框模型),如图所示: 其中包含了四部分内容:element/元素(即图中文字).padding/内边框(图中两个红色边框之间白色部分).border/ ...

  6. TypeScript的类型

    ⒈TypeScript的类型 JavaScript语言的数据类型包括以下7种: 1.boolean(布尔),true || false 2.null,表明null值得特殊关键字,JavaScript是 ...

  7. NOIP2012 DAY1 T2 国王游戏

    题目描述 恰逢 H国国庆,国王邀请n 位大臣来玩一个有奖游戏.首先,他让每个大臣在左.右手上面分别写下一个整数,国王自己也在左.右手上各写一个整数.然后,让这 n 位大臣排成一排,国王站在队伍的最前面 ...

  8. HTNL基础之四

    11.<nav>导航元素 标签定义及使用说明 表示页面中导航链接的部分,例如:传统导航条,侧边栏导航,页内导航,翻页等 <nav> 标签定义导航链接的部分. 并不是所有的 HT ...

  9. spark机器学一Mllib 数据抽象

    spark 提供了两个机器学习库 MLlib 和 ML,MLlib 是 spark 第一个机器学习库,相比于 ML,它更加成熟 rdd 是 spark core 的数据抽象,dataframe 是 s ...

  10. php实现只需要一个QQ号就可以获得用户信息

    <?php // 通过QQ号即可获取用户信息 // 获取QQ头像接口 // http://q1.qlogo.cn/g?b=qq&nk=QQ号&s=100&t=154790 ...