管理es搜索模板
Elasticsearch搜索模板与关系型数据库的存储过程类似。实际就是带变量的查询(使用Mustache模板语言),实际查询时使用模板参数替换变量。
下面示例定义搜索模板:
POST _scripts/<templateid>
{
"script": {
"lang": "mustache",
"source": {
"query": {
"match": {
"title": "{{query_string}}"
}
}
}
}
}
查看已定义的搜索模板:
GET _scripts/<templateid>
执行响应如下:
{
"script" : {
"lang" : "mustache",
"source" : "{\"query\":{\"match\":{\"title\":\"{{query_string}}\"}}}",
"options": {
"content_type" : "application/json; charset=UTF-8"
}
},
"_id": "<templateid>",
"found": true
}
删除搜索模板:
DELETE _scripts/<templateid>
调试es搜索模板
使用搜索模板
可以在某索引下使用搜索模板,需要指定参数。
GET _search/template
{
"id": "<templateid>",
"params": {
"query_string": "search for these words"
}
}
验证搜索模板
GET _render/template
{
"source": "{ \"query\": { \"terms\": {{#toJson}}statuses{{/toJson}} }}",
"params": {
"statuses" : {
"status": [ "pending", "published" ]
}
}
}
通过_render服务渲染模板,输出结果如下:
{
"template_output": {
"query": {
"terms": {
"status": [
"pending", "published"
]
}
}
}
}
存储搜索模板也可以使用下面命令进行验证:
GET _render/template/<template_name>
{
"params": {
"..."
}
}
生成json字符串
使用{{#toJson}}parameter{{/toJson}}指令可以把参数转成json形式,用于复杂查询:
GET _render/template
{
"source": "{ \"query\": { \"terms\": {{#toJson}}statuses{{/toJson}} }}",
"params": {
"statuses" : {
"status": [ "pending", "published" ]
}
}
}
实际结果应该为:
{
"query": {
"terms": {
"status": [
"pending","published"
]
}
}
}
下面是更复杂的示例:
GET _render/template
{
"source": "{\"query\":{\"bool\":{\"must\": {{#toJson}}clauses{{/toJson}} }}}",
"params": {
"clauses": [
{ "term": { "user" : "foo" } },
{ "term": { "user" : "bar" } }
]
}
}
渲染结果为:
{
"query" : {
"bool" : {
"must" : [
{
"term" : {
"user" : "foo"
}
},
{
"term" : {
"user" : "bar"
}
}
]
}
}
}
连接数组值
使用{{#join}}array{{/join}}指令可以连接数组的元素并使用逗号进行分隔:
GET _render/template
{
"source": {
"query": {
"match": {
"emails": "{{#join}}emails{{/join}}"
}
}
},
"params": {
"emails": [ "username@email.com", "lastname@email.com" ]
}
}
渲染结果为:
{
"query" : {
"match" : {
"emails" : "username@email.com,lastname@email.com"
}
}
}
也可以指定分隔符:
GET _render/template
{
"source": {
"query": {
"range": {
"born": {
"gte" : "{{date.min}}",
"lte" : "{{date.max}}",
"format": "{{#join delimiter='||'}}date.formats{{/join delimiter='||'}}"
}
}
}
},
"params": {
"date": {
"min": "2016",
"max": "31/12/2017",
"formats": ["dd/MM/yyyy", "yyyy"]
}
}
}
渲染结果为:
{
"query" : {
"range" : {
"born" : {
"gte" : "2016",
"lte" : "31/12/2017",
"format" : "dd/MM/yyyy||yyyy"
}
}
}
}
指定缺省值
可以使用{{var}}{{^var}}default{{/var}}指令指定缺失值:
{
"source": {
"query": {
"range": {
"line_no": {
"gte": "{{start}}",
"lte": "{{end}}{{^end}}20{{/end}}"
}
}
}
},
"params": { ... }
}
当params参数值为{ “start”: 10, “end”: 15 }时解析结果为:
{
"range": {
"line_no": {
"gte": "10",
"lte": "15"
}
}
}
当params参数值为{ “start”: 10 }时解析结果为:
{
"range": {
"line_no": {
"gte": "10",
"lte": "20"
}
}
}
条件表达式
条件子句不能使用json形式表达,模板必须作为字符串进行传输。假设我们需要在line字段上执行match查询,其中start和end作为行号进行过滤是可选的。参数如下:
{
"params": {
"text": "words to search for",
"line_no": {
"start": 10,
"end": 20
}
}
}
对应查询模板:
{
"query": {
"bool": {
"must": {
"match": {
"line": "{{text}}"
}
},
"filter": {
{{#line_no}}
"range": {
"line_no": {
{{#start}}
"gte": "{{start}}"
{{#end}},{{/end}}
{{/start}}
{{#end}}
"lte": "{{end}}"
{{/end}}
}
}
{{/line_no}}
}
}
}
}
{{#line_no}} 表示如果line_no存在,则解析{{/line_no}}之间的内容。块内的模板语法也类似,都是实现了条件判断功能,伪代码表达如下:
if 条件 then
表达式
end if
实际应用可能会用到if else的功能,在模板中的语法为:{{^line_no}}。
URL编码
{{#url}}value{{/url}}指令能以HTML编码形式对字符串值进行编码,下面示例对url编码:
GET _render/template
{
"source" : {
"query" : {
"term": {
"http_access_log": "{{#url}}{{host}}/{{page}}{{/url}}"
}
}
},
"params": {
"host": "https://www.elastic.co/",
"page": "learn"
}
}
响应结果如下:
{
"template_output" : {
"query" : {
"term" : {
"http_access_log" : "https%3A%2F%2Fwww.elastic.co%2F%2Flearn"
}
}
}
}