搜索模板编辑

搜索模板是您可以使用不同变量运行的已存储搜索。

如果您将 Elasticsearch 用作搜索后端,则可以将来自搜索栏的用户输入作为搜索模板的参数传递。这使您无需向用户公开 Elasticsearch 的查询语法即可运行搜索。

如果您将 Elasticsearch 用于自定义应用程序,则搜索模板允许您在不修改应用程序代码的情况下更改搜索。

创建搜索模板编辑

要创建或更新搜索模板,请使用 创建存储的脚本 API

请求的 source 支持与 搜索 API 的请求正文相同的参数。source 还接受来自开源项目 mustache.javaMustache 变量。

通常,Mustache 变量用双花括号括起来:{{my-var}}。当您运行模板化搜索时,Elasticsearch 会将这些变量替换为 params 中的值。要了解有关 mustache 语法的更多信息,请参阅 Mustache.js 手册 搜索模板必须使用 langmustache

以下请求创建了一个 idmy-search-template 的搜索模板。

response = client.put_script(
  id: 'my-search-template',
  body: {
    script: {
      lang: 'mustache',
      source: {
        query: {
          match: {
            message: '{{query_string}}'
          }
        },
        from: '{{from}}',
        size: '{{size}}'
      },
      params: {
        query_string: 'My query string'
      }
    }
  }
)
puts response
PUT _scripts/my-search-template
{
  "script": {
    "lang": "mustache",
    "source": {
      "query": {
        "match": {
          "message": "{{query_string}}"
        }
      },
      "from": "{{from}}",
      "size": "{{size}}"
    },
    "params": {
      "query_string": "My query string"
    }
  }
}

Elasticsearch 将搜索模板作为 Mustache 脚本 存储在集群状态中。Elasticsearch 在 template 脚本上下文中编译搜索模板。限制或禁用脚本的设置也会影响搜索模板。

验证搜索模板编辑

要使用不同的 params 测试模板,请使用 渲染搜索模板 API

response = client.render_search_template(
  body: {
    id: 'my-search-template',
    params: {
      query_string: 'hello world',
      from: 20,
      size: 10
    }
  }
)
puts response
POST _render/template
{
  "id": "my-search-template",
  "params": {
    "query_string": "hello world",
    "from": 20,
    "size": 10
  }
}

渲染后,模板会输出一个 搜索请求正文

{
  "template_output": {
    "query": {
      "match": {
        "message": "hello world"
      }
    },
    "from": "20",
    "size": "10"
  }
}

您还可以使用 API 来测试内联模板。

response = client.render_search_template(
  body: {
    source: {
      query: {
        match: {
          message: '{{query_string}}'
        }
      },
      from: '{{from}}',
      size: '{{size}}'
    },
    params: {
      query_string: 'hello world',
      from: 20,
      size: 10
    }
  }
)
puts response
POST _render/template
{
    "source": {
      "query": {
        "match": {
          "message": "{{query_string}}"
        }
      },
      "from": "{{from}}",
      "size": "{{size}}"
    },
  "params": {
    "query_string": "hello world",
    "from": 20,
    "size": 10
  }
}

运行模板化搜索编辑

要使用搜索模板运行搜索,请使用 搜索模板 API。您可以为每个请求指定不同的 params

response = client.search_template(
  index: 'my-index',
  body: {
    id: 'my-search-template',
    params: {
      query_string: 'hello world',
      from: 0,
      size: 10
    }
  }
)
puts response
GET my-index/_search/template
{
  "id": "my-search-template",
  "params": {
    "query_string": "hello world",
    "from": 0,
    "size": 10
  }
}

响应使用与 搜索 API 的响应相同的属性。

{
  "took": 36,
  "timed_out": false,
  "_shards": {
    "total": 1,
    "successful": 1,
    "skipped": 0,
    "failed": 0
  },
  "hits": {
    "total": {
      "value": 1,
      "relation": "eq"
    },
    "max_score": 0.5753642,
    "hits": [
      {
        "_index": "my-index",
        "_id": "1",
        "_score": 0.5753642,
        "_source": {
          "message": "hello world"
        }
      }
    ]
  }
}

运行多个模板化搜索编辑

要使用单个请求运行多个模板化搜索,请使用 多搜索模板 API。与多个单独的搜索相比,这些请求通常具有更少的开销和更快的速度。

response = client.msearch_template(
  index: 'my-index',
  body: [
    {},
    {
      id: 'my-search-template',
      params: {
        query_string: 'hello world',
        from: 0,
        size: 10
      }
    },
    {},
    {
      id: 'my-other-search-template',
      params: {
        query_type: 'match_all'
      }
    }
  ]
)
puts response
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" }}

获取搜索模板编辑

要检索搜索模板,请使用 获取存储的脚本 API

response = client.get_script(
  id: 'my-search-template'
)
puts response
GET _scripts/my-search-template

要获取所有搜索模板和其他存储脚本的列表,请使用 集群状态 API

response = client.cluster.state(
  metric: 'metadata',
  pretty: true,
  filter_path: 'metadata.stored_scripts'
)
puts response
GET _cluster/state/metadata?pretty&filter_path=metadata.stored_scripts

删除搜索模板编辑

要删除搜索模板,请使用 删除存储的脚本 API

response = client.delete_script(
  id: 'my-search-template'
)
puts response
DELETE _scripts/my-search-template

设置默认值编辑

要为变量设置默认值,请使用以下语法

{{my-var}}{{^my-var}}default value{{/my-var}}

如果模板化搜索没有在其 params 中指定值,则搜索将使用默认值。例如,以下模板为 fromsize 设置默认值。

response = client.render_search_template(
  body: {
    source: {
      query: {
        match: {
          message: '{{query_string}}'
        }
      },
      from: '{{from}}{{^from}}0{{/from}}',
      size: '{{size}}{{^size}}10{{/size}}'
    },
    params: {
      query_string: 'hello world'
    }
  }
)
puts response
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}} 函数对字符串进行 URL 编码。

response = client.render_search_template(
  body: {
    source: {
      query: {
        term: {
          'url.full' => '{{#url}}{{host}}/{{page}}{{/url}}'
        }
      }
    },
    params: {
      host: 'http://example.com',
      page: 'hello-world'
    }
  }
)
puts response
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}} 函数将数组值连接为逗号分隔的字符串。例如,以下模板连接了两个电子邮件地址。

response = client.render_search_template(
  body: {
    source: {
      query: {
        match: {
          'user.group.emails' => '{{#join}}emails{{/join}}'
        }
      }
    },
    params: {
      emails: [
        '[email protected]',
        '[email protected]'
      ]
    }
  }
)
puts response
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]"
      }
    }
  }
}

您还可以指定自定义分隔符。

response = client.render_search_template(
  body: {
    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'
        ]
      }
    }
  }
)
puts response
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"
        }
      }
    }
  }
}

转换为 JSON编辑

使用 {{#toJson}} 函数将变量值转换为其 JSON 表示形式。

例如,以下模板使用 {{#toJson}} 传递数组。为了确保请求正文是有效的 JSON,source 以字符串格式编写。

response = client.render_search_template(
  body: {
    source: '{ "query": { "terms": { "tags": {{#toJson}}tags{{/toJson}} }}}',
    params: {
      tags: [
        'prod',
        'es01'
      ]
    }
  }
)
puts response
POST _render/template
{
  "source": "{ \"query\": { \"terms\": { \"tags\": {{#toJson}}tags{{/toJson}} }}}",
  "params": {
    "tags": [
      "prod",
      "es01"
    ]
  }
}

模板渲染为

{
  "template_output": {
    "query": {
      "terms": {
        "tags": [
          "prod",
          "es01"
        ]
      }
    }
  }
}

您还可以使用 {{#toJson}} 传递对象。

response = client.render_search_template(
  body: {
    source: '{ "query": {{#toJson}}my_query{{/toJson}} }',
    params: {
      my_query: {
        match_all: {}
      }
    }
  }
)
puts response
POST _render/template
{
  "source": "{ \"query\": {{#toJson}}my_query{{/toJson}} }",
  "params": {
    "my_query": {
      "match_all": { }
    }
  }
}

模板渲染为

{
  "template_output" : {
    "query" : {
      "match_all" : { }
    }
  }
}

您还可以传递对象数组。

response = client.render_search_template(
  body: {
    source: '{ "query": { "bool": { "must": {{#toJson}}clauses{{/toJson}} }}}',
    params: {
      clauses: [
        {
          term: {
            'user.id' => 'kimchy'
          }
        },
        {
          term: {
            'url.domain' => 'example.com'
          }
        }
      ]
    }
  }
)
puts response
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"
            }
          }
        ]
      }
    }
  }
}

使用条件编辑

要创建 if 条件,请使用以下语法

{{#condition}}content{{/condition}}

如果条件变量为 true,则 Elasticsearch 显示其内容。例如,如果 year_scopetrue,则以下模板会搜索过去一年的数据。

response = client.render_search_template(
  body: {
    source: '{ "query": { "bool": { "filter": [ {{#year_scope}} { "range": { "@timestamp": { "gte": "now-1y/d", "lt": "now/d" } } }, {{/year_scope}} { "term": { "user.id": "{{user_id}}" }}]}}}',
    params: {
      year_scope: true,
      user_id: 'kimchy'
    }
  }
)
puts response
POST _render/template
{
  "source": "{ \"query\": { \"bool\": { \"filter\": [ {{#year_scope}} { \"range\": { \"@timestamp\": { \"gte\": \"now-1y/d\", \"lt\": \"now/d\" } } }, {{/year_scope}} { \"term\": { \"user.id\": \"{{user_id}}\" }}]}}}",
  "params": {
    "year_scope": true,
    "user_id": "kimchy"
  }
}

模板渲染为

{
  "template_output" : {
    "query" : {
      "bool" : {
        "filter" : [
          {
            "range" : {
              "@timestamp" : {
                "gte" : "now-1y/d",
                "lt" : "now/d"
              }
            }
          },
          {
            "term" : {
              "user.id" : "kimchy"
            }
          }
        ]
      }
    }
  }
}

如果 year_scopefalse,则模板会搜索任何时间段的数据。

response = client.render_search_template(
  body: {
    source: '{ "query": { "bool": { "filter": [ {{#year_scope}} { "range": { "@timestamp": { "gte": "now-1y/d", "lt": "now/d" } } }, {{/year_scope}} { "term": { "user.id": "{{user_id}}" }}]}}}',
    params: {
      year_scope: false,
      user_id: 'kimchy'
    }
  }
)
puts response
POST _render/template
{
  "source": "{ \"query\": { \"bool\": { \"filter\": [ {{#year_scope}} { \"range\": { \"@timestamp\": { \"gte\": \"now-1y/d\", \"lt\": \"now/d\" } } }, {{/year_scope}} { \"term\": { \"user.id\": \"{{user_id}}\" }}]}}}",
  "params": {
    "year_scope": false,
    "user_id": "kimchy"
  }
}

模板渲染为

{
  "template_output" : {
    "query" : {
      "bool" : {
        "filter" : [
          {
            "term" : {
              "user.id" : "kimchy"
            }
          }
        ]
      }
    }
  }
}

要创建 if-else 条件,请使用以下语法

{{#condition}}if content{{/condition}} {{^condition}}else content{{/condition}}

例如,如果 year_scopetrue,则以下模板会搜索过去一年的数据。否则,它会搜索过去一天的数据。

response = client.render_search_template(
  body: {
    source: '{ "query": { "bool": { "filter": [ { "range": { "@timestamp": { "gte": {{#year_scope}} "now-1y/d" {{/year_scope}} {{^year_scope}} "now-1d/d" {{/year_scope}} , "lt": "now/d" }}}, { "term": { "user.id": "{{user_id}}" }}]}}}',
    params: {
      year_scope: true,
      user_id: 'kimchy'
    }
  }
)
puts response
POST _render/template
{
  "source": "{ \"query\": { \"bool\": { \"filter\": [ { \"range\": { \"@timestamp\": { \"gte\": {{#year_scope}} \"now-1y/d\" {{/year_scope}} {{^year_scope}} \"now-1d/d\" {{/year_scope}} , \"lt\": \"now/d\" }}}, { \"term\": { \"user.id\": \"{{user_id}}\" }}]}}}",
  "params": {
    "year_scope": true,
    "user_id": "kimchy"
  }
}

使用 Mustache 的搜索模板示例编辑

mustache 模板语言定义了您可以在模板中使用的各种标签类型。以下部分描述了其中一些标签类型,并提供了在 Elasticsearch 搜索模板 中使用它们的示例。

Mustache 变量编辑

Mustache 标签通常用双花括号括起来。mustache 变量:{{my-variable}} 是一种 mustache 标签。当您运行模板化搜索时,Elasticsearch 会将这些变量替换为 params 中的值。

例如,请考虑以下搜索模板

response = client.put_script(
  id: 'my-search-template',
  body: {
    script: {
      lang: 'mustache',
      source: {
        query: {
          match: {
            message: '{{query_string}}'
          }
        },
        from: '{{from}}',
        size: '{{size}}'
      }
    }
  }
)
puts response
PUT _scripts/my-search-template
{
  "script": {
    "lang": "mustache",
    "source": {
      "query": {
        "match": {
          "message": "{{query_string}}"
        }
      },
      "from": "{{from}}",
      "size": "{{size}}"
    }
  }
}

使用 params 测试上述搜索模板

response = client.render_search_template(
  body: {
    id: 'my-search-template',
    params: {
      query_string: 'hello world',
      from: 20,
      size: 10
    }
  }
)
puts response
POST _render/template
{
  "id": "my-search-template",
  "params": {
    "query_string": "hello world",
    "from": 20,
    "size": 10
  }
}

渲染后,message 中的 {{query_string}} 将替换为 params 中传递的 hello world

{
  "template_output": {
    "query": {
      "match": {
        "message": "hello world"
      }
    },
    "from": "20",
    "size": "10"
  }
}

如果您的搜索模板没有向您的 query_string 传递值,则消息将被替换为空字符串。

例如

response = client.render_search_template(
  body: {
    id: 'my-search-template',
    params: {
      from: 20,
      size: 10
    }
  }
)
puts response
POST _render/template
{
  "id": "my-search-template",
  "params": {
    "from": 20,
    "size": 10
  }
}

渲染后,模板输出为

{
  "template_output": {
    "query": {
      "match": {
        "message": ""
      }
    },
    "from": "20",
    "size": "10"
  }
}

编辑

节也是一种 Mustache 标签。您可以在搜索模板中将 sections 与嵌套或非嵌套对象一起使用。节以 {{#my-section-variable}} 开头,以 {{/my-section-variable}} 结尾。

以下搜索模板显示了将节与嵌套对象一起使用的示例

response = client.render_search_template(
  body: {
    source: "\n  {\n    \"query\": {\n      \"match\": {\n        {{#query_message}}\n          {{#query_string}}\n        \"message\": \"Hello {{#first_name_section}}{{first_name}}{{/first_name_section}} {{#last_name_section}}{{last_name}}{{/last_name_section}}\"\n          {{/query_string}}\n        {{/query_message}}\n      }\n    }\n  }\n  ",
    params: {
      query_message: {
        query_string: {
          first_name_section: {
            first_name: 'John'
          },
          last_name_section: {
            last_name: 'kimchy'
          }
        }
      }
    }
  }
)
puts response
POST _render/template
{
  "source":
  """
  {
    "query": {
      "match": {
        {{#query_message}}
          {{#query_string}}
        "message": "Hello {{#first_name_section}}{{first_name}}{{/first_name_section}} {{#last_name_section}}{{last_name}}{{/last_name_section}}"
          {{/query_string}}
        {{/query_message}}
      }
    }
  }
  """,
  "params": {
    "query_message": {
       "query_string": {
         "first_name_section": {"first_name": "John"},
         "last_name_section": {"last_name": "kimchy"}
       }
    }
  }
}

模板渲染为

{
  "template_output": {
    "query": {
      "match": {
        "message": "Hello John kimchy"
      }
    }
  }
}
列表编辑

您可以传递对象列表并在搜索模板中循环遍历每个项目。

例如,以下搜索模板结合了 并匹配所有用户名

response = client.put_script(
  id: 'my-search-template',
  body: {
    script: {
      lang: 'mustache',
      source: {
        query: {
          multi_match: {
            query: '{{query_string}}',
            fields: '[{{#text_fields}}{{user_name}},{{/text_fields}}]'
          }
        }
      }
    }
  }
)
puts response
PUT _scripts/my-search-template
{
  "script": {
    "lang": "mustache",
    "source": {
      "query":{
        "multi_match":{
          "query": "{{query_string}}",
          "fields": """[{{#text_fields}}{{user_name}},{{/text_fields}}]"""
        }
      }
    }
  }
}

测试模板

response = client.render_search_template(
  body: {
    id: 'my-search-template',
    params: {
      query_string: 'My string',
      text_fields: [
        {
          user_name: 'John'
        },
        {
          user_name: 'kimchy'
        }
      ]
    }
  }
)
puts response
POST _render/template
{
  "id": "my-search-template",
  "params": {
    "query_string": "My string",
    "text_fields": [
      {
        "user_name": "John"
      },
      {
        "user_name": "kimchy"
      }
    ]
  }
}

渲染后,模板输出

{
  "template_output": {
    "query": {
      "multi_match": {
        "query": "My string",
        "fields": "[John,kimchy,]"
      }
    }
  }
}

以上会导致尾随逗号问题,从而导致无效的 JSON。一种解决方法是包含一个 反向节 并添加一个变量以确保它是数组中的最后一项。

例如

response = client.put_script(
  id: 'my-search-template',
  body: {
    script: {
      lang: 'mustache',
      source: {
        query: {
          multi_match: {
            query: '{{query_string}}',
            fields: '[{{#text_fields}}{{user_name}}{{^last}},{{/last}}{{/text_fields}}]'
          }
        }
      }
    }
  }
)
puts response
PUT _scripts/my-search-template
{
  "script": {
    "lang": "mustache",
    "source": {
      "query":{
        "multi_match":{
          "query": "{{query_string}}",
          "fields": """[{{#text_fields}}{{user_name}}{{^last}},{{/last}}{{/text_fields}}]"""
        }
      }
    }
  }
}

使用变量再次测试 my-search-templatelast 以确定它是数组中的最后一项

response = client.render_search_template(
  body: {
    id: 'my-search-template',
    params: {
      query_string: 'My string',
      text_fields: [
        {
          user_name: 'John',
          last: false
        },
        {
          user_name: 'kimchy',
          last: true
        }
      ]
    }
  }
)
puts response
POST _render/template
{
  "id": "my-search-template",
  "params": {
    "query_string": "My string",
    "text_fields": [
      {
        "user_name": "John",
        "last": false
      },
      {
        "user_name": "kimchy",
        "last": true
      }
    ]
  }
}

渲染后,模板输出

{
  "template_output": {
    "query": {
      "multi_match": {
        "query": "My string",
        "fields": "[John,kimchy]"
      }
    }
  }
}
Lambda编辑

Elasticsearch 具有预构建的自定义函数,以支持将文本转换为特定格式。

要了解有关 mustache lambda 用法的更多信息,请查看 URL 编码字符串连接值转换为 JSON 中的示例。

反向节编辑

当您想设置一次值时,反向节很有用。

要使用反向节,请使用以下语法

{{^my-variable}} content {{/my-variable}}

例如,在以下搜索模板中,如果 name_existsfalse,则使用 Hello World 设置 message,否则将其设置为空字符串。

response = client.render_search_template(
  body: {
    source: {
      query: {
        match: {
          message: '{{^name_exists}}Hello World{{/name_exists}}'
        }
      }
    },
    params: {
      name_exists: false
    }
  }
)
puts response
POST _render/template
{
  "source": {
    "query": {
      "match": {
        "message": "{{^name_exists}}Hello World{{/name_exists}}"
      }
    }
  },
  "params": {
     "name_exists": false
  }
}

它们还可以与 条件默认值 结合使用。

例如,在以下搜索模板中,如果 name_existstrue,则替换 {{query_string}} 的值。如果 name_existsfalse,则将其设置为默认值 World

response = client.render_search_template(
  body: {
    source: {
      query: {
        match: {
          message: 'Hello {{#name_exists}}{{query_string}}{{/name_exists}}{{^name_exists}}World{{/name_exists}}'
        }
      }
    },
    params: {
      query_string: 'Kimchy',
      name_exists: true
    }
  }
)
puts response
POST _render/template
{
  "source": {
    "query": {
      "match": {
        "message": "Hello {{#name_exists}}{{query_string}}{{/name_exists}}{{^name_exists}}World{{/name_exists}}"
      }
    }
  },
  "params": {
    "query_string": "Kimchy",
     "name_exists": true
  }
}

渲染后,模板输出

{
  "template_output": {
    "query": {
      "match": {
        "message": "Hello Kimchy"
      }
    }
  }
}

设置分隔符编辑

您可以在搜索模板中将默认分隔符:双花括号 {{my-variable}} 更改为任何自定义分隔符。

例如,以下搜索模板将默认分隔符更改为单个圆括号 (query_string)

response = client.put_script(
  id: 'my-search-template',
  body: {
    script: {
      lang: 'mustache',
      source: "\n    {\n      \"query\": {\n        \"match\": {\n           {{=( )=}}\n          \"message\": \"(query_string)\"\n          (={{ }}=)\n        }\n      }\n    }\n    "
    }
  }
)
puts response
PUT _scripts/my-search-template
{
  "script": {
    "lang": "mustache",
    "source":
    """
    {
      "query": {
        "match": {
           {{=( )=}}
          "message": "(query_string)"
          (={{ }}=)
        }
      }
    }
    """
  }
}

使用新分隔符测试模板

response = client.render_search_template(
  body: {
    id: 'my-search-template',
    params: {
      query_string: 'hello world'
    }
  }
)
puts response
POST _render/template
{
  "id": "my-search-template",
  "params": {
    "query_string": "hello world"
  }
}

渲染后,模板输出

{
  "template_output": {
    "query": {
      "match": {
        "message": "hello world"
      }
    }
  }
}

不支持的功能编辑

Elasticsearch 搜索模板不支持以下 mustache 功能

  • 局部视图