在 Elasticsearch 当中,如果要使用存储在本地的 Script 文件,往往会使用 Mustache 这种脚本语言。他就是一个模板内容,让我们可以从其他地方得到的参数直接替换内部资源。
使用它而不是内置的 painless 脚本方式,是因为他有更好的模板处理能力,例如 {{#tojson}}XXX{{/tojson}}
的自动扩展。
字符串替换
GET _search/template
{
"source": {
"size": 0,
"query": {
"bool": {
"must": [{"term": {"beat.hostname": "{{hostname}}"} }]
}
}
},
"params": {
"hostname": "host-1"
}
}
Elasticsearch 的 RESTful API 会检查输入的 JSON 语法,这种字符串的替换是最简单的一种方式。无论你在双引号里面怎么写,都是满足 JSON 语法要求的,也就是 API 并没有问题。
tojson 的替换
但是在 Elasticsearch 中我们使用最频繁的应该是 tojson
这种替换规则。我们在 script 里面计算因为他都是 JSON 格式,输出一块内容会经常用这个 {{#tojson}}var-name{{/tojson}}
的内容。
但是,如果还是类似上面的内容就会报告语法错误:
{
"source": {
"size": 0,
"query": {
"bool": {
"must": [{"terms": [{{#tojson}}hostname{{/tojson}}] }]
}
}
},
"params": {
"hostname": ["host-1", "host-2"]
}
}
在 search template 当中有一个特殊的事情,当我们保存一个 mustache 脚本的时候,source
这个域允许直接是一个 字符串 内容。
按照如下的写法就对了:
POST _scripts/test-json
{
"script": {
"lang": "mustache",
"source": """{"size": 0, "query": {"bool": {"must": [{"terms": {{#tojson}}hostname{{/tojson}} }] } } }"""
}
}
在调用的时候,就可以跟正常的脚本一样使用:
GET _search/template
{
"id": "test-json",
"params": {
"hostname": ["host-1", "host-2"]
}
}
在定义 source
的时候,我后面使用了三个双引号。在存储 scripts 的时候,如果定义 "lang": "mustache"
那么 Elasticsearch 的 RESTful API 会自动识别这种格式是合法的。
这样的方式方便了后面的实际 JSON Object 的编写,不用打无数个斜杠了。但是,这种三个引号的语法,实际测试在其他的地方是无效的,会直接报语法错误。例如只是简单的修改 "lang": "painless"
以后。
这个问题虽然 Elasticsearch 官方文档中有说明,但是实在是英文太差,一直有意无意的过滤了 下面这句话
the template should either be stored in a file (see Pre-registered templateedit) or, when used via the REST API, should be written as a string:
这个问题卡了好几天,就因为 source
可以写成 stirng
方式,而这个并不符合写 JSON 的习惯导致。希望遇到这个问题的人能够比我解决的快一些。
其他 Mustache 语法
在 Mustache 官方中,可以根据自己熟悉的语言看一下他的语法文档介绍。
这个东西的适应性还是很广泛的,但是因为我们只在 Elasticsearch 中使用这个模板语言。其他的内容基本上都可以用脚本来解决掉,就不跟这个东西较劲了。后面实际使用中如果发现什么好用,我会更新这里的内容。
预期 {{join}}
应该是一个后面使用过程中,可能会用到的东西。
其他参考
- Mustache - 官方网站,里面有各种语言的 Github 连接,其中大部分都有详细的 Wiki 用于介绍具体的用法;
- Elastic Search Template - 官方对于脚本的使用,其中常见的 Mustache 用法基本上说全了,一定要仔细看啊,我就是吃的看快了的亏😭