搜索模板
编辑搜索模板编辑
搜索模板是您可以使用不同变量运行的已存储搜索。
如果您将 Elasticsearch 用作搜索后端,则可以将来自搜索栏的用户输入作为搜索模板的参数传递。这使您无需向用户公开 Elasticsearch 的查询语法即可运行搜索。
如果您将 Elasticsearch 用于自定义应用程序,则搜索模板允许您在不修改应用程序代码的情况下更改搜索。
创建搜索模板编辑
要创建或更新搜索模板,请使用 创建存储的脚本 API。
请求的 source
支持与 搜索 API 的请求正文相同的参数。source
还接受来自开源项目 mustache.java 的 Mustache 变量。
通常,Mustache 变量用双花括号括起来:{{my-var}}
。当您运行模板化搜索时,Elasticsearch 会将这些变量替换为 params
中的值。要了解有关 mustache 语法的更多信息,请参阅 Mustache.js 手册 搜索模板必须使用 lang
为 mustache
。
以下请求创建了一个 id
为 my-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
中指定值,则搜索将使用默认值。例如,以下模板为 from
和 size
设置默认值。
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_scope
为 true
,则以下模板会搜索过去一年的数据。
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_scope
为 false
,则模板会搜索任何时间段的数据。
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_scope
为 true
,则以下模板会搜索过去一年的数据。否则,它会搜索过去一天的数据。
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-template
:last
以确定它是数组中的最后一项
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_exists
为 false
,则使用 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_exists
为 true
,则替换 {{query_string}}
的值。如果 name_exists
为 false
,则将其设置为默认值 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 功能
- 局部视图