ES 版本
{
"name" : "7120422556f7",
"cluster_name" : "elasticsearch",
"cluster_uuid" : "ZoEJVIlxSFiynXyYnr_pAA",
"version" : {
"number" : "7.4.2",
"build_flavor" : "default",
"build_type" : "docker",
"build_hash" : "2f90bbf7b93631e52bafb59b3b049cb44ec25e96",
"build_date" : "2019-10-28T20:40:44.881551Z",
"build_snapshot" : false,
"lucene_version" : "8.2.0",
"minimum_wire_compatibility_version" : "6.8.0",
"minimum_index_compatibility_version" : "6.0.0-beta1"
},
"tagline" : "You Know, for Search"
}
参考
https://www.elastic.co/guide/en/elasticsearch/reference/current/search-template.html
https://blog.csdn.net/qq330983778/article/details/103625290
语法示例
Elasticsearch 是支持 Mustache (胡子)语法的,这使得即使是通过 json 格式交互,也能充满无限的可能了
{{data}} - 传参
{{#data}} {{/data}} - data没有或为 false 此对标签包裹的内容将不显示
{{^data}} {{/data}} - 和上面一个相反
{{.}} - 表示枚举,可以循环输出整个数组
{{<partials}} - 以>开始表示子模块
{{{data}}} - {{data}}输出会将等特殊字符转译,如果想保持内容原样输出可以使用{{{}}}
{{!comments}} - 可用作注释,不会影响最终结果
常用
相当于 if else
{{#condition}}if content{{/condition}} {{^condition}}else content{{/condition}}
普通模板
删除已创建的模板
DELETE _scripts/my_search_template
创建模板
PUT _scripts/my_search_template
{
"script": {
"lang": "mustache",
"source": {
"from": "{{from}}",
"size": "{{size}}",
"query": {
"term": {
"productCode": "{{productCode}}"
}
}
},
"params": {
"from": null,
"size": null,
"productCode": null
}
}
}
查看已创建的模板
POST _render/template
{
"id": "my_search_template",
"params": {
"from": 0,
"size": 10,
"productCode": "1"
}
}
根据模板查询
GET my_job_index/_search/template
{
"id": "my_search_template",
"params": {
"from": 0,
"size": 10,
"productCode": "1"
}
}
代码块模板
顾名思义,可以在里面添加一些代码块,比如 if else 之类的简单逻辑,还可以使用很多函数,比如 toJson 可以转换为 json 字符串。
删除模板
DELETE _scripts/my_function_template
创建模板
但由于 json 格式的缘故,{{#productCode}} 这种格式不被认可,需要转义,使用 “”" json “”" 这种结构即可
还需要注意的是,最终生成的语法如果是 query:{} 查询会报异常,es 不允许 query 是空的
PUT _scripts/my_function_template
{
"script": {
"lang": "mustache",
"source": """
{
"from": "{{from}}",
"size": "{{size}}",
"_source":[
"systemSource",
"productCode"
],
"query": {
"bool": {
"filter": [
{
"term": {
"systemSource": "sys"
}
}
{{#productCode}}
,
{
"term": {
"productCode": {{productCode}}
}
}
{{/productCode}}
]
}
}
}
""",
"params": {
"from": null,
"size": null,
"productCode": null
}
}
}
执行查询,productCode 有值
GET my_job_index/_search/template
{
"id": "my_function_template",
"params": {
"from": 0,
"size": 10,
"productCode": "1"
}
}
当 productCode 没有值 或者为 false 的时候,则 term 代码块不会出现
“productCode”: null 或者 “productCode”: “” 或者 “productCode”: false
GET my_job_index/_search/template
{
"id": "my_function_template",
"params": {
"from": 0,
"size": 10
}
}
文件模板
在 es 路径下 config/scripts,创建文件,后缀名必须为.mustache,例如:my_complex_template.mustache 内容跟以上 source 一样,my_complex_template 为 id,不过内容包含代码块不用转义
Java 代码
仅供参考
import cn.hutool.json.JSONUtil;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.script.ScriptType;
import org.elasticsearch.script.mustache.SearchTemplateRequest;
import org.elasticsearch.script.mustache.SearchTemplateResponse;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
import java.util.stream.Collectors;
/**
* 功能描述
*
* @author jason
*/
@Slf4j
@RestController
@RequestMapping("/template")
public class EsTemplateController {
@Autowired
private RestHighLevelClient client;
/**
* 模板查询
* http://127.0.0.1:9090/template/search?keyword=2
*/
@SneakyThrows
@GetMapping("/search")
public Object search(@RequestParam(required = false) String keyword) {
SearchTemplateRequest request = new SearchTemplateRequest();
request.setRequest(new SearchRequest("my_job_index"));
request.setScriptType(ScriptType.STORED);
request.setScript("my_function_template");
Map<String, Object> params = new HashMap<>();
params.put("from", 0);
params.put("size", 5);
params.put("productCode", keyword);
request.setScriptParams(params);
SearchTemplateResponse response = client.searchTemplate(request, RequestOptions.DEFAULT);
SearchResponse searchResponse = response.getResponse();
return Arrays.stream(searchResponse.getHits().getHits())
.map(item -> JSONUtil.parse(item.getSourceAsString()))
.collect(Collectors.toList());
}
}