Search Templateedit

The /_search/template endpoint allows to use the mustache language to pre render search requests, before they are executed and fill existing templates with template parameters.

GET /_search/template
{
    "template" : {
      "query": { "match" : { "{{my_field}}" : "{{my_value}}" } },
      "size" : "{{my_size}}"
    },
    "params" : {
        "my_field" : "foo",
        "my_value" : "bar",
        "my_size" : 5
    }
}

For more information on how Mustache templating and what kind of templating you can do with it check out the online documentation of the mustache project.

The mustache language is implemented in elasticsearch as a sandboxed scripting language, hence it obeys settings that may be used to enable or disable scripts per language, source and operation as described in scripting docs [1.6.0] Added in 1.6.0. mustache scripts were always on before and it wasn’t possible to disable them .

More template examplesedit

Filling in a query string with a single valueedit
GET /_search/template
{
    "template": {
        "query": {
            "match": {
                "title": "{{query_string}}"
            }
        }
    },
    "params": {
        "query_string": "search for these words"
    }
}
Passing an array of stringsedit
GET /_search/template
{
  "template": {
    "query": {
      "terms": {
        "status": [
          "{{#status}}",
          "{{.}}",
          "{{/status}}"
        ]
      }
    }
  },
  "params": {
    "status": [ "pending", "published" ]
  }
}

which is rendered as:

{
"query": {
  "terms": {
    "status": [ "pending", "published" ]
  }
}
Default valuesedit

A default value is written as {{var}}{{^var}}default{{/var}} for instance:

{
  "template": {
    "query": {
      "range": {
        "line_no": {
          "gte": "{{start}}",
          "lte": "{{end}}{{^end}}20{{/end}}"
        }
      }
    }
  },
  "params": { ... }
}

When params is { "start": 10, "end": 15 } this query would be rendered as:

{
    "range": {
        "line_no": {
            "gte": "10",
            "lte": "15"
        }
  }
}

But when params is { "start": 10 } this query would use the default value for end:

{
    "range": {
        "line_no": {
            "gte": "10",
            "lte": "20"
        }
    }
}
Conditional clausesedit

Conditional clauses cannot be expressed using the JSON form of the template. Instead, the template must be passed as a string. For instance, let’s say we wanted to run a match query on the line field, and optionally wanted to filter by line numbers, where start and end are optional.

The params would look like:

{
    "params": {
        "text":      "words to search for",
        "line_no": { 
            "start": 10, 
            "end":   20  
        }
    }
}

All three of these elements are optional.

We could write the query as:

{
  "query": {
    "filtered": {
      "query": {
        "match": {
          "line": "{{text}}" 
        }
      },
      "filter": {
        {{#line_no}} 
          "range": {
            "line_no": {
              {{#start}} 
                "gte": "{{start}}" 
                {{#end}},{{/end}} 
              {{/start}} 
              {{#end}} 
                "lte": "{{end}}" 
              {{/end}} 
            }
          }
        {{/line_no}} 
      }
    }
  }
}

Fill in the value of param text

Include the range filter only if line_no is specified

Include the gte clause only if line_no.start is specified

Fill in the value of param line_no.start

Add a comma after the gte clause only if line_no.start AND line_no.end are specified

Include the lte clause only if line_no.end is specified

Fill in the value of param line_no.end

As written above, this template is not valid JSON because it includes the section markers like {{#line_no}}. For this reason, the template should either be stored in a file (see Pre-registered template) or, when used via the REST API, should be written as a string:

"template": "{\"query\":{\"filtered\":{\"query\":{\"match\":{\"line\":\"{{text}}\"}},\"filter\":{{{#line_no}}\"range\":{\"line_no\":{{{#start}}\"gte\":\"{{start}}\"{{#end}},{{/end}}{{/start}}{{#end}}\"lte\":\"{{end}}\"{{/end}}}}{{/line_no}}}}}}"
Pre-registered templateedit

You can register search templates by storing it in the config/scripts directory, in a file using the .mustache extension. In order to execute the stored template, reference it by it’s name under the template key:

GET /_search/template
{
    "template": {
        "file": "storedTemplate" 
    },
    "params": {
        "query_string": "search for these words"
    }
}

Name of the the query template in config/scripts/, i.e., storedTemplate.mustache.

You can also register search templates by storing it in the elasticsearch cluster in a special index named .scripts. There are REST APIs to manage these indexed templates.

POST /_search/template/<templatename>
{
    "template": {
        "query": {
            "match": {
                "title": "{{query_string}}"
            }
        }
    }
}

This template can be retrieved by

GET /_search/template/<templatename>

which is rendered as:

{
    "template": {
        "query": {
            "match": {
                "title": "{{query_string}}"
            }
        }
    }
}

This template can be deleted by

DELETE /_search/template/<templatename>

To use an indexed template at search time use:

GET /_search/template
{
    "template": {
        "id": "templateName" 
    },
    "params": {
        "query_string": "search for these words"
    }
}

Name of the the query template stored in the .scripts index.