Search template = search template = search template

  1. Pre-define the structure of the query statement DSL and reserve parameters
  2. Pass in the parameter value when searching
  3. Render out the full DSL and finally search

Using the search template decouples the DSL from the application and gives you more flexibility to change the query statement.

Such as:

GET _search/template
{
  "source" : {
    "query": {
      "match" : {
        "{{my_field}}" : "{{my_value}}"
      }
    }
  },
  "params" : {
    "my_field" : "message",
    "my_value" : "foo"
  }
}
Copy the code

The resulting DSL is:

{
  "query": {
    "match": {
      "message": "foo"
    }
  }
}
Copy the code

You can reserve parameters in the template by using {{}}, specify corresponding parameter values during query, and fill them into specific query statements for search.


Search template API

To separate search templates from queries, we first need to save and manage the search templates separately.

Save the search template

Use the Scripts API to save the search template (create if it doesn’t exist, overwrite if it does). Example:

POST _scripts/<templateid>
{
  "script": {
    "lang": "mustache",
    "source": {
      "query": {
        "match": {
          "title": "{{query_string}}"
        }
      }
    }
  }
}
Copy the code

Query search templates

GET _scripts/<templateid>
Copy the code

Deleting a Search Template

DELETE _scripts/<templateid>
Copy the code

Using the Search template

Example:

GET _search/template
{
  "id": "<templateid>",
  "params": {
    "query_string": "search words"
  }
}
Copy the code

The parameters in params are the same as those defined in the search template. The previous example of saving the search template was {{query_string}}, so the corresponding parameter for the search here is query_string.

Verify the search template

Sometimes we want to see what the rendered DSL looks like after the search template has entered parameters.

Example:

GET _render/template
{
  "source": "{ \"query\": { \"terms\": {{#toJson}}statuses{{/toJson}} }}",
  "params": {
    "statuses" : {
        "status": [ "pending", "published" ]
    }
  }
}
Copy the code

The result returned is:

{
  "template_output": {
    "query": {
      "terms": {
        "status": [
          "pending",
          "published"
        ]
      }
    }
  }
}
Copy the code

{{#toJson}} {{/toJson}} is converted toJson format.


Search templates that have been saved can view the render results in the following ways:

GET _render/template/<template_name> { "params": { "..." }}Copy the code

useexplainprofileparameter

Example:

GET _search/template
{
  "id": "my_template",
  "params": {
    "status": [ "pending", "published" ]
  },
  "explain": true
}
Copy the code
GET _search/template
{
  "id": "my_template",
  "params": {
    "status": [ "pending", "published" ]
  },
  "profile": true
}
Copy the code

Template rendering

Fill simple values

GET _search/template
{
  "source": {
    "query": {
      "term": {
        "message": "{{query_string}}"
      }
    }
  },
  "params": {
    "query_string": "search words"
  }
}
Copy the code

The rendered DSL looks like this:

{
  "query": {
    "term": {
      "message": "search words"
    }
  }
}
Copy the code

Convert the parameters to JSON

Using {{#toJson}}parameter{{/toJson}} converts the parameters toJson.

GET _search/template
{
  "source": "{ \"query\": { \"terms\": {{#toJson}}statuses{{/toJson}} }}",
  "params": {
    "statuses" : {
        "status": [ "pending", "published" ]
    }
  }
}
Copy the code

The rendered DSL looks like this:

{
  "query": {
    "terms": {
      "status": [
        "pending",
        "published"
      ]
    }
  }
}
Copy the code


An example of rendering an object array:

GET _search/template
{
  "source": "{\"query\":{\"bool\":{\"must\": {{#toJson}}clauses{{/toJson}} }}}",
  "params": {
    "clauses": [
      { "term": { "user" : "foo" } },
      { "term": { "user" : "bar" } }
    ]
  }
}
Copy the code

The render result is:

{
  "query": {
    "bool": {
      "must": [
        { "term": { "user" : "foo" } },
        { "term": { "user" : "bar" } }
      ]
    }
  }
}
Copy the code

Join the array as a string

Use {{#join}}array{{/join}} to join an array as a string.

Example:

GET _search/template
{
  "source": {
    "query": {
      "match": {
        "emails": "{{#join}}emails{{/join}}"
      }
    }
  },
  "params": {
    "emails": [ "aaa", "bbb" ]
  }
}
Copy the code

Render result:

{
  "query" : {
    "match" : {
      "emails" : "aaa,bbb"
    }
  }
}
Copy the code


In addition to the default delimiter, you can also customize the delimiter, as shown in the following example:

{
  "source": {
    "query": {
      "range": {
        "born": {
          "gte": "{{date.min}}",
          "lte": "{{date.max}}",
          "format": "{{#join delimiter='||'}}date.formats{{/join delimiter='||'}}"
        }
      }
    }
  },
  "params": {
    "date": {
      "min": "2016",
      "max": "31/12/2017",
      "formats": [ "dd/MM/yyyy", "yyyy" ]
    }
  }
}
Copy the code

Examples of the {{# join delimiter = ‘| |’}} {{/ join delimiter = ‘| |’}} to join operation means, the delimiter is set to | |, rendering the result:

{
  "query": {
    "range": {
      "born": {
        "gte": "2016",
        "lte": "31/12/2017",
        "format": "dd/MM/yyyy||yyyy"
      }
    }
  }
}
Copy the code

The default value

Set the default values with {{var}}{{^var}}default{{/var}}.

Example:

{ "source": { "query": { "range": { "line_no": { "gte": "{{start}}", "lte": "{{end}}{{^end}}20{{/end}}" } } } }, "params": { ... }}Copy the code

{{end}}{{^end}}20{{/end}} sets the default value of end to 20.

When params is {“start”: 10, “end”: 15}, the render result is:

{
  "range": {
    "line_no": {
      "gte": "10",
      "lte": "15"
    }
  }
}
Copy the code

When params is {“start”: 10}, the default value for end is used and the rendering result is:

{
  "range": {
    "line_no": {
      "gte": "10",
      "lte": "20"
    }
  }
}
Copy the code

Conditional clause

Sometimes our arguments are optional, so we can use the syntax {{#key}} {{/key}}.

Example, assuming the arguments line_no, start, and end are optional, use {{#key}} {{/key}} as follows:

{
  "query": {
    "bool": {
      "must": {
        "match": {
          "line": "{{text}}"
        }
      },
      "filter": {
        {{#line_no}}
          "range": {
            "line_no": {
              {{#start}}
                "gte": "{{start}}"
                {{#end}},{{/end}}
              {{/start}}
              {{#end}}
                "lte": "{{end}}"
              {{/end}}
            }
          }
        {{/line_no}}
      }
    }
  }
}
Copy the code

1. When the parameter is:

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

The render result is:

{
  "query": {
    "bool": {
      "must": {
        "match": {
          "line": "words to search for"
        }
      },
      "filter": {
        "range": {
          "line_no": {
            "gte": "10",
            "lte": "20"
          }
        }
      }
    }
  }
}
Copy the code

2. When the parameter is:

{
  "params": {
    "text": "words to search for"
  }
}
Copy the code

The render result is:

{
  "query": {
    "bool": {
      "must": {
        "match": {
          "line": "words to search for"
        }
      },
      "filter": {}
    }
  }
}
Copy the code

3. When the parameter is:

{
  "params": {
    "text": "words to search for",
    "line_no": {
      "start": 10
    }
  }
}
Copy the code

The render result is:

{
  "query": {
    "bool": {
      "must": {
        "match": {
          "line": "words to search for"
        }
      },
      "filter": {
        "range": {
          "line_no": {
            "gte": 10
          }
        }
      }
    }
  }
}
Copy the code

4. When the parameter is:

{
  "params": {
    "text": "words to search for",
    "line_no": {
      "end": 20
    }
  }
}
Copy the code

The render result is:

{
  "query": {
    "bool": {
      "must": {
        "match": {
          "line": "words to search for"
        }
      },
      "filter": {
        "range": {
          "line_no": {
            "lte": 20
          }
        }
      }
    }
  }
}
Copy the code

It’s important to note that in JSON objects,

{
  "filter": {
    {{#line_no}}
    ...
    {{/line_no}}
  }
}
Copy the code

{{#line_no}} is an invalid JSON format. You must convert it to a JSON string.

URLs coding

HTML encoding can be escaped using {{#url}}value{{/url}}.

Example:

GET _render/template
{
  "source": {
    "query": {
      "term": {
        "http_access_log": "{{#url}}{{host}}/{{page}}{{/url}}"
      }
    }
  },
  "params": {
    "host": "https://www.elastic.co/",
    "page": "learn"
  }
}
Copy the code

Render result:

{
  "template_output": {
    "query": {
      "term": {
        "http_access_log": "https%3A%2F%2Fwww.elastic.co%2F%2Flearn"
      }
    }
  }
}
Copy the code

Mustache basic grammar

The {{}} syntax above is basically mustache language, with some basic grammar rules.

use{{key}}

Template: Hello {{name}}

Input:

{
    "name": "Chris"
}
Copy the code

Output: Hello Chris

use{{{key}}}Avoid escape

All variables are HTML escaped by default.

Template: {{company}}

Input:

{
    "company": "<b>GitHub</b>"
}
Copy the code

Output: & lt; b> GitHub< /b>

Use {{{}}} to avoid escapes.

Template: {{{company}}}

Input:

{
    "company": "<b>GitHub</b>"
}
Copy the code

Output: < b > making < / b >

use{{#key}} {{/key}}Tectonic blocks

1. Templates are ignored when key is false or the list is empty:

    Shown.
    {{#person}}
        Never shown!
    {{/person}}
Copy the code

Input:

{
    "person": false
}
Copy the code

Output:

    Shown.
Copy the code


If key is not null, render the fill template:

    {{#repo}}
        <b>{{name}}</b>
    {{/repo}}
Copy the code

Input:

{
    "repo": [
        { "name": "resque" },
        { "name": "hub" },
        { "name": "rip" }
    ]
}
Copy the code

Output:

    <b>resque</b>
    <b>hub</b>
    <b>rip</b>
Copy the code


Render the template when key is a function:

    {{#wrapped}}
        {{name}} is awesome.
    {{/wrapped}}
Copy the code

Input:

{
    "name": "Willy",
    "wrapped": function() {
        return function(text, render) {
            return "<b>" + render(text) + "</b>"
        }
    }
}
Copy the code

Output:

    <b>Willy is awesome.</b>
Copy the code


If key is not false and is not a list template:

{{#person? }} Hi {{name}}! {{/person? }}Copy the code

Input:

{ "person?" : { "name": "Jon" } }Copy the code

Output:

    Hi Jon!
Copy the code

use{{^key}} {{/key}}Structural antiblock

The syntax of {{^key}} {{/key}} is similar to {{#key}} {{/key}} except that the block content is rendered when the key does not exist, is false, or is an empty list.

Template:

    {{#repo}}
        <b>{{name}}</b>
    {{/repo}}
    {{^repo}}
        No repos :(
    {{/repo}}
Copy the code

Input:

{
    "repo": []
}
Copy the code

Output:

    No repos :(
Copy the code

use{{! }}Add comments

{{! }} Comment content will be ignored.

Template:

<h1>Today{{! ignore me }}.</h1>
Copy the code

Output:

<h1>Today.</h1>
Copy the code

use{{>}}The child module

Template:

base.mustache:
<h2>Names</h2>
{{#names}}
    {{> user}}
{{/names}}

user.mustache:
<strong>{{name}}</strong>
Copy the code

In fact, it is equivalent to:

<h2>Names</h2>
{{#names}}
    <strong>{{name}}</strong>
{{/names}}
Copy the code

use{{= =}}Custom delimiter

Sometimes we need to change the default delimiter {{}}, so we can use {{= =}}} to customize the delimiter.

Such as:

{{= < % % > =}}Copy the code

The delimiter is defined as <% %>, so that the original {{key}} is used as <%key%>. To use:

= % > < % = {{}}Copy the code

I changed the delimiter back to {{}}.

For more details on the syntax, check the official document Mustache Language.

conclusion

Using the Search Template effectively decouples the search, meaning that the application only needs to focus on the search parameters and the returned results, not the SPECIFIC DSL query statement being used, which DSL is used is managed separately by the search template.