搜索模板
编辑搜索模板
编辑搜索模板是一种存储的搜索,您可以使用不同的变量来运行它。
如果您使用 Elasticsearch 作为搜索后端,您可以将搜索栏中的用户输入作为搜索模板的参数传递。这使您可以在不向用户公开 Elasticsearch 的查询语法的情况下运行搜索。
如果您将 Elasticsearch 用于自定义应用程序,搜索模板允许您更改搜索,而无需修改应用程序的代码。
创建搜索模板
编辑要创建或更新搜索模板,请使用 创建存储的脚本 API。
请求的 source
支持与 搜索 API 的请求正文相同的参数。source
还接受来自开源项目 mustache.java 的 Mustache 变量。
通常,Mustache 变量包含在双花括号中:{{my-var}}
。当您运行模板化搜索时,Elasticsearch 会将这些变量替换为 params
中的值。要了解有关 mustache 语法的更多信息,请参阅 Mustache.js 手册。搜索模板必须使用 mustache
的 lang
。
以下请求创建一个 id
为 my-search-template
的搜索模板。
resp = client.put_script( id="my-search-template", script={ "lang": "mustache", "source": { "query": { "match": { "message": "{{query_string}}" } }, "from": "{{from}}", "size": "{{size}}" } }, ) print(resp)
response = client.put_script( id: 'my-search-template', body: { script: { lang: 'mustache', source: { query: { match: { message: '{{query_string}}' } }, from: '{{from}}', size: '{{size}}' } } } ) puts response
const response = await client.putScript({ id: "my-search-template", script: { lang: "mustache", source: { query: { match: { message: "{{query_string}}", }, }, from: "{{from}}", size: "{{size}}", }, }, }); console.log(response);
PUT _scripts/my-search-template { "script": { "lang": "mustache", "source": { "query": { "match": { "message": "{{query_string}}" } }, "from": "{{from}}", "size": "{{size}}" } } }
Elasticsearch 将搜索模板作为 Mustache 脚本存储在集群状态中。Elasticsearch 在 template
脚本上下文中编译搜索模板。限制或禁用脚本的设置也会影响搜索模板。
验证搜索模板
编辑要使用不同的 params
测试模板,请使用 渲染搜索模板 API。
resp = client.render_search_template( id="my-search-template", params={ "query_string": "hello world", "from": 20, "size": 10 }, ) print(resp)
response = client.render_search_template( body: { id: 'my-search-template', params: { query_string: 'hello world', from: 20, size: 10 } } ) puts response
const response = await client.renderSearchTemplate({ id: "my-search-template", params: { query_string: "hello world", from: 20, size: 10, }, }); console.log(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 来测试内联模板。
resp = client.render_search_template( source={ "query": { "match": { "message": "{{query_string}}" } }, "from": "{{from}}", "size": "{{size}}" }, params={ "query_string": "hello world", "from": 20, "size": 10 }, ) print(resp)
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
const response = await client.renderSearchTemplate({ source: { query: { match: { message: "{{query_string}}", }, }, from: "{{from}}", size: "{{size}}", }, params: { query_string: "hello world", from: 20, size: 10, }, }); console.log(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
。
resp = client.search_template( index="my-index", id="my-search-template", params={ "query_string": "hello world", "from": 0, "size": 10 }, ) print(resp)
response = client.search_template( index: 'my-index', body: { id: 'my-search-template', params: { query_string: 'hello world', from: 0, size: 10 } } ) puts response
const response = await client.searchTemplate({ index: "my-index", id: "my-search-template", params: { query_string: "hello world", from: 0, size: 10, }, }); console.log(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。与多个单独的搜索相比,这些请求通常具有更少的开销和更快的速度。
resp = client.msearch_template( index="my-index", search_templates=[ {}, { "id": "my-search-template", "params": { "query_string": "hello world", "from": 0, "size": 10 } }, {}, { "id": "my-other-search-template", "params": { "query_type": "match_all" } } ], ) print(resp)
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
const response = await client.msearchTemplate({ index: "my-index", search_templates: [ {}, { id: "my-search-template", params: { query_string: "hello world", from: 0, size: 10, }, }, {}, { id: "my-other-search-template", params: { query_type: "match_all", }, }, ], }); console.log(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。
resp = client.get_script( id="my-search-template", ) print(resp)
response = client.get_script( id: 'my-search-template' ) puts response
const response = await client.getScript({ id: "my-search-template", }); console.log(response);
GET _scripts/my-search-template
要获取所有搜索模板和其他存储的脚本的列表,请使用 集群状态 API。
resp = client.cluster.state( metric="metadata", pretty=True, filter_path="metadata.stored_scripts", ) print(resp)
response = client.cluster.state( metric: 'metadata', pretty: true, filter_path: 'metadata.stored_scripts' ) puts response
const response = await client.cluster.state({ metric: "metadata", pretty: "true", filter_path: "metadata.stored_scripts", }); console.log(response);
GET _cluster/state/metadata?pretty&filter_path=metadata.stored_scripts
删除搜索模板
编辑要删除搜索模板,请使用 删除存储的脚本 API。
resp = client.delete_script( id="my-search-template", ) print(resp)
response = client.delete_script( id: 'my-search-template' ) puts response
const response = await client.deleteScript({ id: "my-search-template", }); console.log(response);
DELETE _scripts/my-search-template
设置默认值
编辑要为变量设置默认值,请使用以下语法
{{my-var}}{{^my-var}}default value{{/my-var}}
如果模板化搜索未在其 params
中指定值,则搜索将使用默认值。例如,以下模板为 from
和 size
设置默认值。
resp = client.render_search_template( source={ "query": { "match": { "message": "{{query_string}}" } }, "from": "{{from}}{{^from}}0{{/from}}", "size": "{{size}}{{^size}}10{{/size}}" }, params={ "query_string": "hello world" }, ) print(resp)
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
const response = await client.renderSearchTemplate({ source: { query: { match: { message: "{{query_string}}", }, }, from: "{{from}}{{^from}}0{{/from}}", size: "{{size}}{{^size}}10{{/size}}", }, params: { query_string: "hello world", }, }); console.log(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 编码。
resp = client.render_search_template( source={ "query": { "term": { "url.full": "{{#url}}{{host}}/{{page}}{{/url}}" } } }, params={ "host": "http://example.com", "page": "hello-world" }, ) print(resp)
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
const response = await client.renderSearchTemplate({ source: { query: { term: { "url.full": "{{#url}}{{host}}/{{page}}{{/url}}", }, }, }, params: { host: "http://example.com", page: "hello-world", }, }); console.log(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}}
函数将数组值连接为逗号分隔的字符串。例如,以下模板连接两个电子邮件地址。
resp = client.render_search_template( source={ "query": { "match": { "user.group.emails": "{{#join}}emails{{/join}}" } } }, params={ "emails": [ "[email protected]", "[email protected]" ] }, ) print(resp)
response = client.render_search_template( body: { source: { query: { match: { 'user.group.emails' => '{{#join}}emails{{/join}}' } } }, params: { emails: [ '[email protected]', '[email protected]' ] } } ) puts response
const response = await client.renderSearchTemplate({ source: { query: { match: { "user.group.emails": "{{#join}}emails{{/join}}", }, }, }, params: { emails: ["[email protected]", "[email protected]"], }, }); console.log(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]" } } } }
您还可以指定自定义分隔符。
resp = client.render_search_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" ] } }, ) print(resp)
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
const response = await client.renderSearchTemplate({ 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"], }, }, }); console.log(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
以字符串格式编写。
resp = client.render_search_template( source="{ \"query\": { \"terms\": { \"tags\": {{#toJson}}tags{{/toJson}} }}}", params={ "tags": [ "prod", "es01" ] }, ) print(resp)
response = client.render_search_template( body: { source: '{ "query": { "terms": { "tags": {{#toJson}}tags{{/toJson}} }}}', params: { tags: [ 'prod', 'es01' ] } } ) puts response
const response = await client.renderSearchTemplate({ source: '{ "query": { "terms": { "tags": {{#toJson}}tags{{/toJson}} }}}', params: { tags: ["prod", "es01"], }, }); console.log(response);
POST _render/template { "source": "{ \"query\": { \"terms\": { \"tags\": {{#toJson}}tags{{/toJson}} }}}", "params": { "tags": [ "prod", "es01" ] } }
模板渲染为
{ "template_output": { "query": { "terms": { "tags": [ "prod", "es01" ] } } } }
您还可以使用 {{#toJson}}
传递对象。
resp = client.render_search_template( source="{ \"query\": {{#toJson}}my_query{{/toJson}} }", params={ "my_query": { "match_all": {} } }, ) print(resp)
response = client.render_search_template( body: { source: '{ "query": {{#toJson}}my_query{{/toJson}} }', params: { my_query: { match_all: {} } } } ) puts response
const response = await client.renderSearchTemplate({ source: '{ "query": {{#toJson}}my_query{{/toJson}} }', params: { my_query: { match_all: {}, }, }, }); console.log(response);
POST _render/template { "source": "{ \"query\": {{#toJson}}my_query{{/toJson}} }", "params": { "my_query": { "match_all": { } } } }
模板渲染为
{ "template_output" : { "query" : { "match_all" : { } } } }
您还可以传递对象数组。
resp = client.render_search_template( source="{ \"query\": { \"bool\": { \"must\": {{#toJson}}clauses{{/toJson}} }}}", params={ "clauses": [ { "term": { "user.id": "kimchy" } }, { "term": { "url.domain": "example.com" } } ] }, ) print(resp)
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
const response = await client.renderSearchTemplate({ source: '{ "query": { "bool": { "must": {{#toJson}}clauses{{/toJson}} }}}', params: { clauses: [ { term: { "user.id": "kimchy", }, }, { term: { "url.domain": "example.com", }, }, ], }, }); console.log(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
,则以下模板会搜索过去一年的数据。
resp = client.render_search_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" }, ) print(resp)
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
const response = await client.renderSearchTemplate({ 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", }, }); console.log(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
,则模板会搜索任何时间段的数据。
resp = client.render_search_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" }, ) print(resp)
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
const response = await client.renderSearchTemplate({ 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", }, }); console.log(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
,则以下模板会搜索过去一年的数据。否则,它会搜索过去一天的数据。
resp = client.render_search_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" }, ) print(resp)
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
const response = await client.renderSearchTemplate({ 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", }, }); console.log(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
中的值。
例如,考虑以下搜索模板
resp = client.put_script( id="my-search-template", script={ "lang": "mustache", "source": { "query": { "match": { "message": "{{query_string}}" } }, "from": "{{from}}", "size": "{{size}}" } }, ) print(resp)
response = client.put_script( id: 'my-search-template', body: { script: { lang: 'mustache', source: { query: { match: { message: '{{query_string}}' } }, from: '{{from}}', size: '{{size}}' } } } ) puts response
const response = await client.putScript({ id: "my-search-template", script: { lang: "mustache", source: { query: { match: { message: "{{query_string}}", }, }, from: "{{from}}", size: "{{size}}", }, }, }); console.log(response);
PUT _scripts/my-search-template { "script": { "lang": "mustache", "source": { "query": { "match": { "message": "{{query_string}}" } }, "from": "{{from}}", "size": "{{size}}" } } }
使用 params
测试上述搜索模板
resp = client.render_search_template( id="my-search-template", params={ "query_string": "hello world", "from": 20, "size": 10 }, ) print(resp)
response = client.render_search_template( body: { id: 'my-search-template', params: { query_string: 'hello world', from: 20, size: 10 } } ) puts response
const response = await client.renderSearchTemplate({ id: "my-search-template", params: { query_string: "hello world", from: 20, size: 10, }, }); console.log(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
,则消息将被替换为空字符串。
例如
resp = client.render_search_template( id="my-search-template", params={ "from": 20, "size": 10 }, ) print(resp)
response = client.render_search_template( body: { id: 'my-search-template', params: { from: 20, size: 10 } } ) puts response
const response = await client.renderSearchTemplate({ id: "my-search-template", params: { from: 20, size: 10, }, }); console.log(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}}
结尾。
以下搜索模板显示了使用带有嵌套对象的节的示例
resp = client.render_search_template( 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" } } } }, ) print(resp)
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
const response = await client.renderSearchTemplate({ 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", }, }, }, }, }); console.log(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" } } } }
列表
编辑您可以传递对象列表,并在搜索模板中循环访问每个项目。
例如,以下搜索模板结合了 节 并匹配所有用户名
resp = client.put_script( id="my-search-template", script={ "lang": "mustache", "source": { "query": { "multi_match": { "query": "{{query_string}}", "fields": "[{{#text_fields}}{{user_name}},{{/text_fields}}]" } } } }, ) print(resp)
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
const response = await client.putScript({ id: "my-search-template", script: { lang: "mustache", source: { query: { multi_match: { query: "{{query_string}}", fields: "[{{#text_fields}}{{user_name}},{{/text_fields}}]", }, }, }, }, }); console.log(response);
PUT _scripts/my-search-template { "script": { "lang": "mustache", "source": { "query":{ "multi_match":{ "query": "{{query_string}}", "fields": """[{{#text_fields}}{{user_name}},{{/text_fields}}]""" } } } } }
测试模板
resp = client.render_search_template( id="my-search-template", params={ "query_string": "My string", "text_fields": [ { "user_name": "John" }, { "user_name": "kimchy" } ] }, ) print(resp)
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
const response = await client.renderSearchTemplate({ id: "my-search-template", params: { query_string: "My string", text_fields: [ { user_name: "John", }, { user_name: "kimchy", }, ], }, }); console.log(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。一种解决方法是包含一个 倒置节 并添加一个变量,以确保它是数组中的最后一个项目。
例如
resp = client.put_script( id="my-search-template", script={ "lang": "mustache", "source": { "query": { "multi_match": { "query": "{{query_string}}", "fields": "[{{#text_fields}}{{user_name}}{{^last}},{{/last}}{{/text_fields}}]" } } } }, ) print(resp)
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
const response = await client.putScript({ id: "my-search-template", script: { lang: "mustache", source: { query: { multi_match: { query: "{{query_string}}", fields: "[{{#text_fields}}{{user_name}}{{^last}},{{/last}}{{/text_fields}}]", }, }, }, }, }); console.log(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}}]""" } } } } }
再次使用变量:last
测试 my-search-template
,以确定它是数组中的最后一个项目
resp = client.render_search_template( id="my-search-template", params={ "query_string": "My string", "text_fields": [ { "user_name": "John", "last": False }, { "user_name": "kimchy", "last": True } ] }, ) print(resp)
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
const response = await client.renderSearchTemplate({ id: "my-search-template", params: { query_string: "My string", text_fields: [ { user_name: "John", last: false, }, { user_name: "kimchy", last: true, }, ], }, }); console.log(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
,则 message
设置为 Hello World
,否则将其设置为空字符串。
resp = client.render_search_template( source={ "query": { "match": { "message": "{{^name_exists}}Hello World{{/name_exists}}" } } }, params={ "name_exists": False }, ) print(resp)
response = client.render_search_template( body: { source: { query: { match: { message: '{{^name_exists}}Hello World{{/name_exists}}' } } }, params: { name_exists: false } } ) puts response
const response = await client.renderSearchTemplate({ source: { query: { match: { message: "{{^name_exists}}Hello World{{/name_exists}}", }, }, }, params: { name_exists: false, }, }); console.log(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
。
resp = client.render_search_template( source={ "query": { "match": { "message": "Hello {{#name_exists}}{{query_string}}{{/name_exists}}{{^name_exists}}World{{/name_exists}}" } } }, params={ "query_string": "Kimchy", "name_exists": True }, ) print(resp)
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
const response = await client.renderSearchTemplate({ source: { query: { match: { message: "Hello {{#name_exists}}{{query_string}}{{/name_exists}}{{^name_exists}}World{{/name_exists}}", }, }, }, params: { query_string: "Kimchy", name_exists: true, }, }); console.log(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)
。
resp = client.put_script( id="my-search-template", script={ "lang": "mustache", "source": "\n {\n \"query\": {\n \"match\": {\n {{=( )=}}\n \"message\": \"(query_string)\"\n (={{ }}=)\n }\n }\n }\n " }, ) print(resp)
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
const response = await client.putScript({ id: "my-search-template", script: { lang: "mustache", source: '\n {\n "query": {\n "match": {\n {{=( )=}}\n "message": "(query_string)"\n (={{ }}=)\n }\n }\n }\n ', }, }); console.log(response);
PUT _scripts/my-search-template { "script": { "lang": "mustache", "source": """ { "query": { "match": { {{=( )=}} "message": "(query_string)" (={{ }}=) } } } """ } }
使用新的分隔符测试模板
resp = client.render_search_template( id="my-search-template", params={ "query_string": "hello world" }, ) print(resp)
response = client.render_search_template( body: { id: 'my-search-template', params: { query_string: 'hello world' } } ) puts response
const response = await client.renderSearchTemplate({ id: "my-search-template", params: { query_string: "hello world", }, }); console.log(response);
POST _render/template { "id": "my-search-template", "params": { "query_string": "hello world" } }
渲染后,模板输出
{ "template_output": { "query": { "match": { "message": "hello world" } } } }
不支持的功能
编辑以下 mustache 功能在 Elasticsearch 搜索模板中不受支持
- 局部