Search Template:搜索模板

我们在写查询条件时,有很多时候条件是相同的,只是传入的值是不同的,为了一劳永逸,我们可以定义一个搜索模板,以后在用到相同的查询的时候,不需要再次编写,直接使用该模板,传入需要查询的值即可。

定义搜索模板(或者更新)

POST _scripts/order_id_template
{
   "script": {
       "lang": "mustache",
       "source": {
           "query": {
               "match": {
                   "order_id": "{{orderId}}"
               }
           }
       }
   }
}

每个搜索模板是对应的name,上面的模板的nameorder_id_template,是为了在使用模板的时候使用该值。上面的模板的作用是搜索指定orderId的文档。

查看搜索模板

GET _scripts/order_id_template

删除搜索模板

DELETE _scripts/order_id_template

使用搜索模板

给出上面搜索模板的例子。

GET alibaba_taobao/_search/template
{
    "id": "order_id_template", 
    "params": {
        "orderId": "570111"
    }
}

下面介绍搜索模板的语法,注意下面的语法都是验证模板方法,不是提前注册的模板。

1.参数

{{param}} 将搜索模板中的参数用真实值替换。

GET _render/template
{
    "source" : {
      "query": { "match" : { "{{my_field}}" : "{{my_value}}" } },
      "size" : "{{my_size}}"
    },
    "params" : {
        "my_field" : "message",
        "my_value" : "some message",
        "my_size" : 5
    }
}

上面的语法将转换为

"source" : {
     "query": { "match" : { "message" : "some message" } },
     "size" : "5"
}
2.产生转换为JSON

{{#toJson}}param{{/toJson}} 将参数转成转换JSON,一般用于map或者数组

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

转换后的语法

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

因为语法中含有{{#toJson}}所以语法不是json串了,所以要转换成字符串。

3.对参数进行拼接操作

{{#join}}param{{/join}}

GET _search/template
{
  "source": {
    "query": {
      "match": {
        "email": "{{#join}}emails{{/join}}"
      }
    }
  },
  "params": {
    "emails": [ "mayun", "@alibaba.com" ]
  }
}

将数组参数emails,中值用默认的连接符,连接,转换后的语法为

"source": {
    "query": {
      "match": {
        "email": "mayun,@alibaba.com"
      }
    }
  }

也可以定义连接符,例如用-作为连接符{{#join delimiter='-'}emails{{{/join delimiter='-'}}

4.判断

{{#param}}B{{/param}}
如果查询中没有使用该param参数,则B不会作为查询的条件

{
  "query": {
    "bool": {
      "filter": {
        {{#line_no}}
          "range": {
            "line_no": {
              {{#start}}
                "gte": "{{start}}"
                {{#end}},{{/end}}
              {{/start}}
              {{#end}}
                "lte": "{{end}}" 
              {{/end}}
            }
          }
        {{/line_no}}
      }
    }
  }
}

同样上面的语法是失败的,因为存在 {{#line_no}}等语法,不能正确的json串,所以要把上面的语法转化为字符串

GET _render/template
{
    "source": "{\"query\": {\"bool\": {\n\"filter\": {\n{{#line_no}} \"range\": {\"line_no\": {\n{{#start}} \"gte\": \"{{start}}\" {{#end}},{{/end}} {{/start}}{{#end}} \"lte\": \"{{end}}\" {{/end}}}}{{/line_no}}}}}}",
    "params": {
        "orderId": "123",
        "orderfield": "order_id",
        "line_no": {
            "start": 10,
            "end": 20
        }
    }
}

转化的语法为

{
  "template_output" : {
    "query" : {
      "bool" : {
        "filter" : {
          "range" : {
            "line_no" : {
              "gte" : "10",
              "lte" : "20"
            }
          }
        }
      }
    }
  }
}

还有类似的if-else语法

{{#param}}
	逻辑1
{{/param}}
{{^param}}
	逻辑2
{{/param}}

如果存在line_no则执行逻辑1,否则执行逻辑2

5.默认值

{{param}}{{^param}}默认值{{/parma}},如果param有值,则使用传入的值,否则使用默认值。

6.url编码

避免因为地址中的特殊符号而导致保存或者查询异常
{{#url}}value{{/url}}

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

转化后的语法为

{
  "template_output" : {
    "query" : {
      "term" : {
        "http_access_log" : "https%3A%2F%2Fwww.elastic.co%2F%2Flearn"
      }
    }
  }
}
7.验证索引模板的正确性

_render 上面的语法都是使用该功能验证的,就不赘述了。