Search templatesedit
A search template is a stored search you can run with different variables.
If you use Elasticsearch as a search backend, you can pass user input from a search bar as parameters for a search template. This lets you run searches without exposing Elasticsearch’s query syntax to your users.
If you use Elasticsearch for a custom application, search templates let you change your searches without modifying your app’s code.
Create a search templateedit
To create or update a search template, use the create stored script API.
The request’s source
supports the same parameters as the search API's request body.source
also accepts Mustache variables, from an open source project mustache.java.
Typically Mustache variables are enclosed in
double curly brackets: {{my-var}}
. When you run a templated search, Elasticsearch
replaces these variables with values from params
. To learn more about mustache syntax - see Mustache.js manual Search templates must use a lang
of mustache
.
The following request creates a search template with an id
of
my-search-template
.
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 stores search templates as Mustache scripts in the
cluster state. Elasticsearch compiles search templates in the template
script context.
Settings that limit or disable scripts also affect search templates.
Validate a search templateedit
To test a template with different params
, use the
render search template API.
POST _render/template { "id": "my-search-template", "params": { "query_string": "hello world", "from": 20, "size": 10 } }
When rendered, the template outputs a search request body.
{ "template_output": { "query": { "match": { "message": "hello world" } }, "from": "20", "size": "10" } }
You can also use the API to test inline templates.
POST _render/template { "source": { "query": { "match": { "message": "{{query_string}}" } }, "from": "{{from}}", "size": "{{size}}" }, "params": { "query_string": "hello world", "from": 20, "size": 10 } }
Run a templated searchedit
To run a search with a search template, use the search
template API. You can specify different params
with each request.
GET my-index/_search/template { "id": "my-search-template", "params": { "query_string": "hello world", "from": 0, "size": 10 } }
The response uses the same properties as the search API's response.
{ "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" } } ] } }
Run multiple templated searchesedit
To run multiple templated searches with a single request, use the multi search template API. These requests often have less overhead and faster speeds than multiple individual searches.
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" }}
Get search templatesedit
To retrieve a search template, use the get stored script API.
GET _scripts/my-search-template
To get a list of all search templates and other stored scripts, use the cluster state API.
GET _cluster/state/metadata?pretty&filter_path=metadata.stored_scripts
Delete a search templateedit
To delete a search template, use the delete stored script API.
DELETE _scripts/my-search-template
Set default valuesedit
To set a default value for a variable, use the following syntax:
{{my-var}}{{^my-var}}default value{{/my-var}}
If a templated search doesn’t specify a value in its params
, the search uses
the default value instead. For example, the following template sets defaults
for from
and size
.
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 encode stringsedit
Use the {{#url}}
function to URL encode a string.
POST _render/template { "source": { "query": { "term": { "url.full": "{{#url}}{{host}}/{{page}}{{/url}}" } } }, "params": { "host": "http://example.com", "page": "hello-world" } }
The template renders as:
{ "template_output": { "query": { "term": { "url.full": "http%3A%2F%2Fexample.com%2Fhello-world" } } } }
Concatenate valuesedit
Use the {{#join}}
function to concatenate array values as a comma-delimited
string. For example, the following template concatenates two email addresses.
POST _render/template { "source": { "query": { "match": { "user.group.emails": "{{#join}}emails{{/join}}" } } }, "params": { "emails": [ "user1@example.com", "user_one@example.com" ] } }
The template renders as:
{ "template_output": { "query": { "match": { "user.group.emails": "user1@example.com,user_one@example.com" } } } }
You can also specify a custom delimiter.
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"] } } }
The template renders as:
{ "template_output": { "query": { "range": { "user.effective.date": { "gte": "2098", "lte": "06/05/2099", "format": "dd/MM/yyyy||yyyy" } } } } }
Convert to JSONedit
Use the {{#toJson}}
function to convert a variable value to its JSON
representation.
For example, the following template uses {{#toJson}}
to pass an array. To
ensure the request body is valid JSON, the source
is written in the string
format.
POST _render/template { "source": "{ \"query\": { \"terms\": { \"tags\": {{#toJson}}tags{{/toJson}} }}}", "params": { "tags": [ "prod", "es01" ] } }
The template renders as:
{ "template_output": { "query": { "terms": { "tags": [ "prod", "es01" ] } } } }
You can also use {{#toJson}}
to pass objects.
POST _render/template { "source": "{ \"query\": {{#toJson}}my_query{{/toJson}} }", "params": { "my_query": { "match_all": { } } } }
The template renders as:
{ "template_output" : { "query" : { "match_all" : { } } } }
You can also pass an array of objects.
POST _render/template { "source": "{ \"query\": { \"bool\": { \"must\": {{#toJson}}clauses{{/toJson}} }}}", "params": { "clauses": [ { "term": { "user.id": "kimchy" } }, { "term": { "url.domain": "example.com" } } ] } }
The template renders as:
{ "template_output": { "query": { "bool": { "must": [ { "term": { "user.id": "kimchy" } }, { "term": { "url.domain": "example.com" } } ] } } } }
Use conditionsedit
To create if conditions, use the following syntax:
{{#condition}}content{{/condition}}
If the condition variable is true
, Elasticsearch displays its content. For example, the
following template searches data from the past year if year_scope
is true
.
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" } }
The template renders as:
{ "template_output" : { "query" : { "bool" : { "filter" : [ { "range" : { "@timestamp" : { "gte" : "now-1y/d", "lt" : "now/d" } } }, { "term" : { "user.id" : "kimchy" } } ] } } } }
If year_scope
is false
, the template searches data from any time period.
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" } }
The template renders as:
{ "template_output" : { "query" : { "bool" : { "filter" : [ { "term" : { "user.id" : "kimchy" } } ] } } } }
To create if-else conditions, use the following syntax:
{{#condition}}if content{{/condition}} {{^condition}}else content{{/condition}}
For example, the following template searches data from the past year if
year_scope
is true
. Otherwise, it searches data from the past day.
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" } }