技术标签: Elastic Elasticsearch elasticsearch 大数据
我们发现一些用户经常编写了一些非常冗长和复杂的查询 - 在很多情况下,相同的查询会一遍又一遍地执行,但是会有一些不同的值作为参数来查询。在这种情况下,我们觉得使用一个 search template(搜索模板)来做这样的工作非常合适。搜索模板允许你使用可在执行时定义的参数定义查询。
Search template 的好处是:
首先,我们来定义一个 search template 来看看它到底是什么东西。使用_scripts端点将模板存储在集群状态中。在 search template中使用的语言叫做 mustache。
POST _scripts/my_search_template
{
"script": {
"lang": "mustache",
"source": {
"query": {
"match": {
"{
{my_field}}": "{
{my_value}}"
}
}
}
}
}
在这里,我们定义了一个叫做 my_search_template 的 search template。如果我们想更新这个 search template,我们可以直接进行修改,然后再次运行上面的命令即可。
我们可以试验如下的命令来验证我们的 search template:
POST _render/template
{
"id": "my_search_template",
"params": {
"my_field": "city",
"my_value": "Beijing"
}
}
上述命令输出搜索请求正文:
{
"template_output": {
"query": {
"match": {
"city": "Beijing"
}
}
}
}
我们也可以使用如下的 API 来测试 inline templates:
POST _render/template
{
"source": {
"query": {
"match": {
"{
{my_field}}": "{
{my_value}}"
}
}
},
"params": {
"my_field": "city",
"my_value": "Beijing"
}
}
上面的命令将返回和上述命令一样的结果。
要使用搜索模板运行搜索,请使用搜索模板 API。 你可以为每个请求指定不同的参数。
在 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 的i ndex 之中。我们现在可以使用我们刚才定义的 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 是工作的。
要使用单个请求运行多个模板化搜索,请使用多搜索模板 API。 与多个单独的搜索相比,这些请求通常具有更少的开销和更快的速度:
GET my-index/_msearch/template
{ }
{ "id": "my-search-template", "params": { "query_string": "hello world", "from": 0, "size": 10 }}
{ }
{ "id": "my-other-search-template", "params": { "query_type": "match_all" }}
要为变量设置默认值,请使用以下语法:
{
{my-var}}{
{^my-var}}default value{
{/my-var}}
如果模板化搜索未在其参数中指定值,则搜索将使用默认值。 例如,以下模板设置了 from 和 size 的默认值。
POST _render/template
{
"source": {
"query": {
"match": {
"message": "{
{query_string}}"
}
},
"from": "{
{from}}{
{^from}}0{
{/from}}",
"size": "{
{size}}{
{^size}}10{
{/size}}"
},
"params": {
"query_string": "hello world"
}
}
使用 { {#url}} 函数对字符串进行 URL 编码。
POST _render/template
{
"source": {
"query": {
"term": {
"url.full": "{
{#url}}{
{host}}/{
{page}}{
{/url}}"
}
}
},
"params": {
"host": "http://example.com",
"page": "hello-world"
}
}
模板呈现为:
{
"template_output": {
"query": {
"term": {
"url.full": "http%3A%2F%2Fexample.com%2Fhello-world"
}
}
}
}
使用 { {#join}} 函数将数组值连接为逗号分隔的字符串。 例如,以下模板连接两个电子邮件地址。
POST _render/template
{
"source": {
"query": {
"match": {
"user.group.emails": "{
{#join}}emails{
{/join}}"
}
}
},
"params": {
"emails": [ "[email protected]", "[email protected]" ]
}
}
模板呈现为:
{
"template_output": {
"query": {
"match": {
"user.group.emails": "[email protected],[email protected]"
}
}
}
}
你还可以指定自定义分隔符。
POST _render/template
{
"source": {
"query": {
"range": {
"user.effective.date": {
"gte": "{
{date.min}}",
"lte": "{
{date.max}}",
"format": "{
{#join delimiter='||'}}date.formats{
{/join delimiter='||'}}"
}
}
}
},
"params": {
"date": {
"min": "2098",
"max": "06/05/2099",
"formats": ["dd/MM/yyyy", "yyyy"]
}
}
}
模板呈现为:
{
"template_output": {
"query": {
"range": {
"user.effective.date": {
"gte": "2098",
"lte": "06/05/2099",
"format": "dd/MM/yyyy||yyyy"
}
}
}
}
}
使用 { {#toJson}} 函数将变量值转换为其 JSON 表示形式。
例如,以下模板使用 { {#toJson}} 传递数组。 为了确保请求体是有效的 JSON,source 以字符串格式编写。
POST _render/template
{
"source": "{ \"query\": { \"terms\": { \"tags\": {
{#toJson}}tags{
{/toJson}} }}}",
"params": {
"tags": [
"prod",
"es01"
]
}
}
模板呈现为:
{
"template_output": {
"query": {
"terms": {
"tags": [
"prod",
"es01"
]
}
}
}
}
你还可以使用 { {#toJson}} 传递对象。
POST _render/template
{
"source": "{ \"query\": {
{#toJson}}my_query{
{/toJson}} }",
"params": {
"my_query": {
"match_all": { }
}
}
}
模板呈现为:
{
"template_output" : {
"query" : {
"match_all" : { }
}
}
}
你还可以传递一个对象数组:
POST _render/template
{
"source": "{ \"query\": { \"bool\": { \"must\": {
{#toJson}}clauses{
{/toJson}} }}}",
"params": {
"clauses": [
{
"term": {
"user.id": "kimchy"
}
},
{
"term": {
"url.domain": "example.com"
}
}
]
}
}
模板呈现为:
{
"template_output": {
"query": {
"bool": {
"must": [
{
"term": {
"user.id": "kimchy"
}
},
{
"term": {
"url.domain": "example.com"
}
}
]
}
}
}
}
在 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"
}
}
}
]
}
}
显然这次我们搜索到我们想要的结果。
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:
DELETE _scripts/<templateid>
我们可以通过 _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
}
}
}
]
}
}
}
}
显然,这个就是我们想要的结果。
参考:
文章浏览阅读47次。linux 路由表维护查看 Linux 内核路由表使用下面的 route 命令可以查看 Linux 内核路由表。# routeDestination Gateway Genmask Flags Metric Ref Use Iface192.168.0.0 * 255.255.255.0 ...
文章浏览阅读5.2k次。参考How to normalize image in openCV?cv::Mat img3;img2.convertTo(img3, CV_32F, 1.0 / 255, 0);_cv mat 归一化
文章浏览阅读3.5k次。unity shader浅析_unity 内置shader
文章浏览阅读2.4k次。PCA画图 (rna-seq下游)rm(list=ls())mydata <- read.table("C:/Users/gao/Desktop/all.id.txt",header =TRUE,quote='\t',skip = 1) smpleNames <- c('mesc_1','mesc_1','mesc_2','mesc_2','mesc_3','mesc_3','mesc_4','mesc_4','mesc_5','mesc_5','mesc_6','mesc_6','mes_pca rnaseq 绘图
文章浏览阅读1.3k次。资深HR告诉你:应聘如何百发百中?
文章浏览阅读8.7k次。这里有个功能,当点击时间或者取消选择时间,要触发事件来进行操作。但是当时间组件type为dates时就不能点击触发chang事件,点击确定按钮才会触发。这里在是对这个进行监听来触发事件<el-date-picker v-model="shangkedata" type="dates" clearable placeholder="选择日期" format="yyyy - MM - dd" value-format="yy_vue3中el-date-picker没有点击事件吗?
文章浏览阅读9.8k次,点赞19次,收藏37次。https://baike.baidu.com/item/IBM%20Simon/6165040https://www.dw.com/en/nokias-smartphone-25-years-since-it-changed-the-world/a-58841329https://en.wikipedia.org/wiki/Nokia_9000_Communicator要问现代人每天接触时间最长的物品是什么?那肯定是手机了。与只能打电话、发短信的初代手机相比,现在的手机早已脱胎换骨,集实用与智能于一_第一部智能手机
文章浏览阅读876次。2019独角兽企业重金招聘Python工程师标准>>> ..._uft默认的运行结果的窗口
文章浏览阅读225次。A Gentle Introduction to Probabilistic Modeling and Density Estimation in Machine LearningAndA Detailed Explanation of Variational Auto-EncoderbyJiyang [email protected]/2..._vae模型详细
文章浏览阅读689次。微商微营销,现在很流行。加粉,加好友也是很多做微商朋友最关心的问题。选择一款适合自己的微信开通检测软件,不但可以提高自己的工作效率、还可以让你体验不一样的加粉效果。小编就来和大家分享一下正确选择微信开通检测软件的方法。 首先看软件的功能:服务范围是否广泛,实用;站内数据是否丰富。 然后看软件的价格:检测体统成本还是需要的,不要相信免费的,但是也不会很昂贵,比如雄霸微信账_测及人工检测,为您提供更好的使用体验 广告检测范围
文章浏览阅读68次。萝卜青菜,各有所爱。一般说来,用人部门对于简历的筛选是各有不同的。当然,也并不是没有相同之处。在与人力资源经理交谈中发现,内容的真实性是大家一致认定的标准之一;详实、不长篇累牍的简历比较让人认可;那些精心设计、贴着艺术照和写真照的简历,则鲜有用人单位投赞成票。 投放简历,是求职者找工作的第一步,而简历也就成了求职的敲门砖。是否有机会参加下一步的考核赢来工作的机会,全看这敲门...
文章浏览阅读283次。文章目录[1京东、摩拜——“裁员进行时”][2知乎、斗鱼——“突然大变脸”][3锤子、美图——“时间足够”“补偿足够”][4裁员应该是什么补偿标准?]回头看2018年进入第四季度后,宏观经济的不景气终于传导到了个人身上,“裁员”消息一波接着一波。烧钱最猛的各互联网大厂员工,率先沦为泡沫破灭时的“代价”,年底被裁,哀鸿遍野。据统计,从京东、知乎、锤子、到近期的美团、摩拜等..._年底了,互联网公司裁员汇总