Search template — Elastic Stack 实战手册

本文涉及的产品
Elasticsearch Serverless通用抵扣包,测试体验金 200元
简介: Elasticsearch 允许使用模板语言 mustache 来预设搜索逻辑,在实际搜索时,通过参数中的键值,对来替换模板中的占位符,最终完成搜索

970X90.png

· 更多精彩内容,请下载阅读全本《Elastic Stack实战手册》

· 加入创作人行列,一起交流碰撞,参与技术圈年度盛事吧

创作人:骆潇龙

Elasticsearch 允许使用模板语言 mustache 来预设搜索逻辑,在实际搜索时,通过参数中的键值,对来替换模板中的占位符,最终完成搜索。该方式将搜索逻辑封闭在 Elasticsearch 中,可以使下游服务,在不知道具体搜索逻辑的情况下完成数据检索。我们以 Kibana 自带的航班数据kibana_sample_data_flights为基础,以按航班号搜索为例,简单介绍搜索模板的使用。

第一步,创建 ID 为 testSearchTemplate 的搜索模板,语句如下

POST _scripts/testSearchTemplate
{ 
  "script": {
    "lang": "mustache",   #使用 mustache 模板语言
    "source": {   # 脚本内容
      "query": {    # 搜索逻辑
        "term": {
          "FlightNum": {
            "value": "{{FlightNum}}"  # 占位符 FlightNum
          }
        }
      }
    }
  }
}

第二步,传参搜索数据,语句如下

GET kibana_sample_data_flights/_search/template
{
  "id": "testSearchTemplate",     # 使用的模板ID
  "params": {
    "FlightNum": "9HY9SWR"    # 占位符替换的值
  }
}

以上两步就是使用模板搜索数据,该逻辑等同于下面这个搜索

GET kibana_sample_data_flights/_search
{
  "query": {
    "term": {
      "FlightNum": {
        "value": "9HY9SWR"
      }
    }
  }
}

API介绍

下面我们从搜索模板的生命周期:创建、查看、使用、删除来展开介绍模板搜索相关 API。

准备

在正式介绍之前,我们先来说一说关于模板搜索的几个预备知识。

首先,如果使用的 Elasticsearch 集群开启了安全功能,那么角色对操作的索引必须要有read权限。

其次,搜索模板使用的语法是Mustache

更多的关于该种脚本语言的介绍以及功能请查看其官方 文档: https://mustache.github.io/mustache.5.html

最后,模板搜索属于 Elasticsearch 中 Script 功能的扩展, Script 的限定及用法基本都适用于模板搜索。比如,集群关于 Script 的配置也会影响模板搜索,配置项script.allowed_types可规范模板搜索接受的类型( inline / stored / both ),script.allowed_contexts也会限制模板搜索可进行的操作。

创建

搜索模板的创建与 Elasticsearch 其它脚本的创建一样,都是发送 1 个POST请求即可。

如下所示:

POST _scripts/<templateId>  # 1
{
  "script": {
    "lang": "mustache", # 2
    "source": {   # 3
      "query": {
          "term": {
            "FlightNum": {
              "value": "{{FlightNum}}"  # 可变参数 FlightNum
            }
          }
        }
    }
  }
}
  1. _scripts/<templateId>发送 POST 请求来创建搜索模板,其中<templateId>是你为该模板设置的 ID,搜索时会用到该 ID
  2. lang 参数配置的是搜索模板使用的脚本语言为mustache
  3. source 参数配置的是搜索模板的具体内容,该部分的格式参照 Elasticsearch 搜索的请求 body,需要搜索时填充的值使用mustache语法,配置占位符即可,比如本例中的占位符就是{{FlightNum}}

查看

当我们想查看之前创建的模板内容,或者验证某个 ID 的模板是否存在时,可以向_scripts/<templateId>发送 GET 请求来获取模板的具体内容。

示例如下:

GET _scripts/<templateId>  # 1
{
  "_id" : "testSearchTemplate",  # 2
  "found" : true,  # 3
  "script" : {   # 4
    "lang" : "mustache", 
    "source" : """{"query":{"term":{"FlightNum":{"value":"{{FlightNum}}"}}}}""", 
    "options" : {  # 5
      "content_type" : "application/json; charset=UTF-8"
    }
  }
}
  1. 请求的 path 为_scripts/<templateId>,其中<templateId>为你要查询的模板 Id,请求类型为 GET
  2. 返回的 body 中,_id 属性再次表明此次查询的模板 ID,本示例查询的是之前创建的testSearchTemplate模板
  3. found 属性表明此次查询是否查到结果,如果模板 ID 存在则此值为 true,反之为 false
  4. script 就是该搜索模板的具体内容与保存时相同。核心有 lang 属性表示脚本语法,source 属性存放脚本具体内容
  5. script 属性中的 Options 属性是非必要其它脚本属性,默认会有 content_type 属性,该属性保存查询时 http 请求的content-type ,默认为application/json; charset=UTF-8

删除

在一个搜索模板完成了它的使命后,我们需要及时删除它,因为 Elasticsearch 默认缓存脚本的数据量是有上限的,删除的方式很简单,发送一个DELETE请求即可。

示例如下:

DELETE _scripts/<templateId>   #1

<templateId>为要删除的搜索模板的 ID,比如_scripts/testSearchTemplate 表示的就是删除 ID 为testSearchTemplate的搜索模板。

使用

搜索模板的使用就是在搜索时,直接发送占位符的值,即可执行预设搜索语句。由于还是在搜索的范畴,所以发送请求的 path 是_search/template

下面是关于使用搜索模板进行查询的示例:

GET <index>/_search/template?<query_parameters> #1
{
  "source": """{"query": {"term": {"FlightNum": {"value": "{{FlightNum}}"}}}}""",  #2
  "id": "testSearchTemplate", # 3
  "params": {  # 4
    "FlightNum": "9HY9SWR"
  },
  "profile": true, # 5
  "explain": true  # 6
}

模板搜索发送的地址为<index>/_search/template,与搜索一样<index>处为选填参数,你可以指定搜索的索引,不指定则表示搜索全部索引。

因为本质上还是属于搜索的范畴,所以一些搜索参数在模板搜索是也可以使用,比如:

  • scroll(可选,时长):表示本搜索需要支持游标搜索,游标过期时间为配置值
  • ccs_minimize_roundtrips(可选,布尔值):如果为 true 则在跨集群搜索时最小化集群间交互。默认为 true
  • expand_wildcards(可选,字符串):表示索引通配符作用的范围,可配置为全部(all)、打开索引(open)、关闭索引(closed)、隐藏索引(hidden,需要与open或closed结合使用)、不允许通配符(none)
  • explain(可选,布尔值):表示返回结果是否带计算得分的详细信息,默认是false
  • ignore_throttled(可选,布尔值):如果为 true 则表示查询忽略被限制的索引,被限制的索引一般指被冻结(freeze)的索引,该值默认是 true
  • ignore_unavailable(可选,布尔值):如果为 true 则表示关闭的索引不在搜索范围内,默认值为 true
  • preference(可选,字符串):指定执行该操作的节点或分片,默认是随机的
  • rest_total_hits_as_int(可选,布尔值):如果为 true 则 hits.total 将会是个数值而非一个对象,默认为 false
  • routing(可选, 字符串):配置搜索执行的路由
  • search_type(可选,字符串):这是搜索的类型,可选值有:query_then_fetch、dfs_query_then_fetch
  • source 字段:用于配置搜索模板,该字段与 ID 字段冲突只能二选一,使用 source 表示不使用保存的模板而使用本模板
  • id 字段:表示本次查询使用的搜索模板 ID,该字段与 source 字 段冲突只能二选一
  • params 字段:配置的 key-value 值将替换模板中的占位符执行搜索
  • profile 字段:是可选字段,表示返回结果中是否有 Elasticsearch 执行搜索的一些元信息
  • explain 字段:是可选字段,与 http 中搜索参数配置的 explain 含义一样,表示结果是否带计算得分的详细信息

上述搜索返回结果如下:

{
  "took" : 1,
  "timed_out" : false,
  "_shards" : {
    "total" : 1,
    "successful" : 1,
    "skipped" : 0,
    "failed" : 0
  },
  "hits" : {
    "total" : {
      "value" : 1,
      "relation" : "eq"
    },
    "max_score" : 9.071844,
    "hits" : [
      {
        "_shard" : "[kibana_sample_data_flights][0]",
        "_node" : "ydZx8i8HQBe69T4vbYm30g",
        "_index" : "kibana_sample_data_flights",
        "_type" : "_doc",
        "_id" : "KPRFDHkB9LctWlE3WLqj",
        "_score" : 9.071844,
        "_source" : {
          "FlightNum" : "9HY9SWR",
          "DestCountry" : "AU",
          "OriginWeather" : "Sunny"
        },
        "_explanation" : {}  # 计算得分的逻辑
      }
    ]
  },
  "profile" : {} # 搜索细节信息
}

其它

本部分将介绍关于模板搜索的一些小技巧。通常情况下我们写的搜索模板,往往是很难一次就配置正确的,因此需要频繁的测试我们写的模板,与参数结合后是否是我们预期的搜索语句,这时我们就可以使用以下这个请求,来校验模板使用是否正确。

GET _render/template # 1
{
  "source": """{"query": {"term": {"FlightNum": {"value": "{{FlightNum}}"}}}}""" ,# 2
  "params": { # 3
    "FlightNum": "9HY9SWR"
  }
}

{  # 4
  "template_output" : {
    "query" : {
      "term" : {
        "FlightNum" : {
          "value" : "9HY9SWR"
        }
      }
    }
  }
}
  1. _render/template发送 GET 请求来验证模板是否正确
  2. source 字段为要验证的搜索模板,该字段可以省略,如果省略需要在 path 处指定模板iID,比如_render/template/testSearchTemplate
  3. params 字段为模板使用的参数
  4. 此 JSON 就是该请求的返回,template_output字段就是在使用此params下搜索模板生成的查询语句

模板语言 mustache 有许多功能,这里再介绍几个比较常见的。

比如我们使用占位符替换的不是一个字符串,而是一个对象或数组对象,那么我们可以用{{#toJson}}{{/toJson}}来实现,

具体如下:

GET _render/template
{
  "source": """{"query": {"term": {"FlightNum": {{#toJson}}FlightNum{{/toJson}}  }}}""", # 1
  "params": { # 2
    "FlightNum": {
      "value":"9HY9SWR"
    }
  }
}

{ # 3
  "template_output" : {
    "query" : {
      "term" : {
        "FlightNum" : {
          "value" : "9HY9SWR"
        }
      }
    }
  }
}

在配置模板时,我们将FlightNum的 value 配置为{{#toJson}}FlightNum{{/toJson}},即表示占位符FlightNum是一个对象

在配置 params 时,我们将 FlightNum 的值设置为一个 JSON 对象{ "value":"9HY9SWR"}

通过校验请求的返回,可以看到{{#toJson}}FlightNum{{/toJson}}被替换为对象{ "value":"9HY9SWR"}

Mustache 还能在将变量套入模板时做一些处理,比如将数组变量组合成字符串放入模板、设置占位符的默认值,以及对 URL 转码。

示例如下

GET _render/template
{
  "source": {
    "query": {
      "term": {
        "FlightNum": "{{#join delimiter='||'}}FlightNums{{/join delimiter='||'}}", #1
        "DestCountry":"{{DestCountry}}{{^DestCountry}}AU{{/DestCountry}}",#2
        "Dest": "{{#url}}{{Dest}}{{/url}}"#3
      }
    }
  },
  "params": {
    "FlightNums": [
      "9HY9SWR",
      "adf2c1"
    ],
    "Dest":"http://www.baidu.com"
  }
}

{
  "template_output" : {
    "query" : {
      "term" : {
        "FlightNum" : "9HY9SWR||adf2c1", # 4
        "DestCountry" : "AU", #5
        "Dest" : "http%3A%2F%2Fwww.baidu.com" # 6
      }
    }
  }
}

第一个模板使用{{#join delimiter='||'}}{{/join delimiter='||'}}设置了数组合并的分割字符为 "||",传参时FlightNums配置的为["9HY9SWR","adf2c1"],而生成的则是 #4 处的9HY9SWR||adf2c1

第二个模板使用{{^DestCountry}}AU{{/DestCountry}}设置了占位符 DestCountry 的默认值为 AU,这样我们在params中并未配置 DestCountry 的值,但生成的 #5 处自动用 AU 替换了占位符

第三个模板我们用{{#url}}{{/url}}声明了此处是一个 URL,需要进行转义,则在 #6 处配置的http://www.baidu.com变为了http%3A%2F%2Fwww.baidu.com

相关实践学习
以电商场景为例搭建AI语义搜索应用
本实验旨在通过阿里云Elasticsearch结合阿里云搜索开发工作台AI模型服务,构建一个高效、精准的语义搜索系统,模拟电商场景,深入理解AI搜索技术原理并掌握其实现过程。
ElasticSearch 最新快速入门教程
本课程由千锋教育提供。全文搜索的需求非常大。而开源的解决办法Elasricsearch(Elastic)就是一个非常好的工具。目前是全文搜索引擎的首选。本系列教程由浅入深讲解了在CentOS7系统下如何搭建ElasticSearch,如何使用Kibana实现各种方式的搜索并详细分析了搜索的原理,最后讲解了在Java应用中如何集成ElasticSearch并实现搜索。 &nbsp;
相关文章
|
存储 SQL JSON
Elasticsearch Search API之搜索模板(search Template)
Elasticsearch Search API之搜索模板(search Template)
Elasticsearch Search API之搜索模板(search Template)
|
2月前
|
JSON Java API
(ELK)ElasticSearch8.7 搭配 SpringDataElasticSearch5.1 的使用
截至2023/7/11日,全网最全最直白的SpringDataElasticSearch5.1
228 2
|
4月前
|
人工智能 自然语言处理 JavaScript
17种RAG实现方法大揭秘
RAG(检索增强生成)通过结合外部知识库与LLM生成能力,有效解决大模型知识滞后与幻觉问题。本文详解三类策略、17种实现方案,涵盖文档分块、检索排序与反馈机制,并提供工程选型指南,助力构建高效智能系统。
977 0
|
缓存 关系型数据库 MySQL
MySQL执行计划选择策略:揭秘查询优化的艺术
【10月更文挑战第15天】 在数据库性能优化中,选择最优的执行计划是提升查询效率的关键。MySQL作为一个强大的关系型数据库管理系统,提供了复杂的查询优化器来生成执行计划。本文将深入探讨如何选择合适的执行计划,以及为什么某些计划更优。
380 2
|
人工智能 架构师 Java
传智教育引通义灵码进课堂,为技术人才教育学习提效
7 月 17 日,阿里云与传智教育在阿里巴巴云谷园区签署合作协议,双方将基于阿里云智能编程助手通义灵码在课程共建、品牌合作及产教融合等多个领域展开合作,共同推进 AI 教育及相关业务的发展,致力于培养适应未来社会需求的高素质技术人才。
|
存储 人工智能 数据处理
Elasticsearch 8 RAG 技术分享
本文介绍了Elasticsearch 8 在RAG场景方面的发展历程、技术演进、未来发展方向和产品能力。
998 8
|
安全 Linux 应用服务中间件
从零开始启动、配置、保护你的云服务器并搭建一个简单的网站
本文详细介绍了如何准备原料、搭建基础环境、进行安全防护、建设网站、管理证书以及开启BBR优化网络性能。主要内容包括获取健康云服务器、配置SSH登录、创建非root用户、启用密钥认证、安装Nginx、申请TLS证书、配置HTTPS自动跳转及优化网络性能等步骤。通过本文,读者可以掌握从零开始搭建个人网站的全过程。
462 2
从零开始启动、配置、保护你的云服务器并搭建一个简单的网站
|
负载均衡 网络协议 算法
|
12月前
|
监控 网络协议 数据挖掘
固定窗口和滑动窗口,你真的分得清吗?快来看看!
滑动窗口是一种用于实时数据统计和分析的技术,通过不断移动的时间窗口捕捉最新数据变化。它常用于限流、实时数据分析和TCP协议中的流量控制,能够提供持续更新的统计数据,有效控制请求流量,避免系统过载。与固定窗口相比,滑动窗口更加动态和灵活,适合实时监控和快速响应。
577 0
|
存储 分布式计算 搜索推荐
ES自定义评分机制:function_score查询详解
ES自定义评分机制:function_score查询详解
1991 0
ES自定义评分机制:function_score查询详解

热门文章

最新文章