Elasticsearch:search template
我们发现一些用户经常编写了一些非常冗长和复杂的查询 - 在很多情况下,相同的查询会一遍又一遍地执行,但是会有一些不同的值作为参数来查询。在这种情况下,我们觉得使用一个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的更多相关文章
- Elasticsearch:跨集群搜索 Cross-cluster search (CCS)
转载自:https://blog.csdn.net/UbuntuTouch/article/details/104588232 跨集群搜索(cross-cluster search)使您可以针对一个或 ...
- elasticsearch.net search入门使用指南中文版(翻译)
elasticsearch.net search入门使用指南中文版,elasticsearch.Net是一个非常底层且灵活的客户端,它不在意你如何的构建自己的请求和响应.它非常抽象,因此所有的elas ...
- elasticsearch.net search入门使用指南中文版
原文:http://edu.dmeiyang.com/book/nestusing.html elasticsearch.net为什么会有两个客户端? Elasticsearch.Net是一个非常底层 ...
- Elasticsearch URI search 查询语法整理
Elasticsearch URI search 一.请求体查询与空查询 1. 请求体查询(request body search) 简单查询语句(lite)是一种有效的命令行adhoc查询.但是,如 ...
- Elasticsearch:Index生命周期管理入门
如果您要处理时间序列数据,则不想将所有内容连续转储到单个索引中. 取而代之的是,您可以定期将数据滚动到新索引,以防止数据过大而又缓慢又昂贵. 随着索引的老化和查询频率的降低,您可能会将其转移到价格较低 ...
- Go标准库:Go template用法详解
本文只介绍template的语法和用法,关于template包的函数.方法.template的结构和原理,见:深入剖析Go template. 入门示例 以下为test.html文件的内容,里面使用了 ...
- Python:Day53 Template基础
一.模板由 html代码+逻辑控制代码 组成 二.逻辑控制代码的组成 1.变量(使用双大括号来引用变量) 语法格式:{{ var_name }} -----------------------Temp ...
- Django学习笔记(二):使用Template让HTML、CSS参与网页建立
Django学习笔记(二):使用Template让HTML.CSS参与网页建立 通过本文章实现: 了解Django中Template的使用 让HTML.CSS等参与网页建立 利用静态文件应用网页样式 ...
- 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 ...
随机推荐
- centos7:ssh免密登陆设置及常见错误
目录 一.免密登录设置 二.常见错误 三.CentOS7再ssh-copy-id时的错误 一.免密登录设置 1.使用root用户登录,进入到目录/root/.ssh 2.执行命令:ssh-keygen ...
- svn clean up
1.下载sqlite3.exe 2.找到你项目的.svn文件,查看是否存在wc.db3.将sqlite3.exe放到.svn的同级目录4.启动cmd执行sqlite3 .svn/wc.db " ...
- java中Super到底是什么意思?必须举例说明!
[学习笔记] 3."超"关键字(super keyword) Super是一个参考(或说指针)指向他紧邻的父类(见下面的例子).用super可以指向被隐藏的父类的同名成员. 3.1 ...
- 如何使用RedisTemplate访问Redis数据结构之字符串操作
Redis 数据结构简介 Redis 可以存储键与5种不同数据结构类型之间的映射,这5种数据结构类型分别为String(字符串).List(列表).Set(集合).Hash(散列)和 Zset(有序集 ...
- spring-redis使用
导包 注入调用 opsForValue() opsForList() redisTemplate 配置 ,为了 对key采用string序列化方式 ...
- python保留字及其说明
保留字 说 明 and 用于表达式运算,逻辑与操作 as 用于类型转换 assert 断言,用于判断变量或条件表达式的值是否为真 break 中断循环语句的执行 class 用于定义类 con ...
- 有关this指针指向问题
在下面两个写法中 var obj = { foo: function () {} }; var foo = obj.foo; // 写法一 obj.foo() // 写法二 foo() 上面代码中,虽 ...
- docker部署redis
镜像获取 docker pull redis:4.0 ##当前最新版本 docker images 启动 docker run --name redis-huiyuan -p : -v $PWD/da ...
- SpringBoot中获取spring.profiles.active的值
一.网上很多采用@Profile("dev")的方式获取,但是这个是类级别的 二.开发中可能需要代码级别 1.刚开始我想通过classpath下的文件读取方式,麻烦死了,于是换了个 ...
- Java lesson08 Homework
1:1. 写一个类Param,声明四个成员变量a.b.c.d,分别赋予四种访问权限. (1)试验在同一个包中的另一个类里能访问哪几个变量? (2)试验在不同包中的另一个类里能访问哪几个变量? (3)试 ...