Search 模板

原文链接 : https://www.elastic.co/guide/en/elasticsearch/reference/5.0/search-template.html

译文链接 : http://www.apache.wiki/display/Elasticsearch

贡献者 : @Josh

/_search/template endpoint 允许我们在执行搜索请求和使用模板参数填充现有模板之前,能够使用 mustache 语言预先呈现搜索请求。

  1. GET /_search/template
  2. {
  3. "inline" : {
  4. "query": { "match" : { "{{my_field}}" : "{{my_value}}" } },
  5. "size" : "{{my_size}}"
  6. },
  7. "params" : {
  8. "my_field" : "foo",
  9. "my_value" : "bar",
  10. "my_size" : 5
  11. }
  12. }

关于 Mustache templating 以及你可以使用哪种模板,请参考 mustache 项目在线文档

NOTE:

elasticsearch 中实现的 mustache 语言是作为一种沙箱(sandboxed) 脚本语言,因此它遵守相关设置,这些设置可能是为了启用或禁用 脚本文档 中描述的每个语言、源和操作。

更多的模板案例

使用单个值填充查询字符串

  1. GET /_search/template
  2. {
  3. "inline": {
  4. "query": {
  5. "match": {
  6. "title": "{{query_string}}"
  7. }
  8. }
  9. },
  10. "params": {
  11. "query_string": "search for these words"
  12. }
  13. }

将参数转换为 JSON

{{#toJson}}parameter{{/toJson}} 函数可以用来转换参数(比如 maps 和 array)为它们的 JSON 形式。

  1. GET /_search/template
  2. {
  3. "inline": "{ \"query\": { \"terms\": { \"status\": {{#toJson}}status{{/toJson}} }}}",
  4. "params": {
  5. "status": [ "pending", "published" ]
  6. }
  7. }

其呈现为:

  1. {
  2. "query": {
  3. "terms": {
  4. "status": [
  5. "pending",
  6. "published"
  7. ]
  8. }
  9. }
  10. }

更复杂的例子代替一个 JSON 对象数组:

  1. {
  2. "inline": "{\"query\":{\"bool\":{\"must\": {{#toJson}}clauses{{/toJson}} }}}",
  3. "params": {
  4. "clauses": [
  5. { "term": "foo" },
  6. { "term": "bar" }
  7. ]
  8. }
  9. }

呈现为:

  1. {
  2. "query" : {
  3. "bool" : {
  4. "must" : [
  5. {
  6. "term" : "foo"
  7. },
  8. {
  9. "term" : "bar"
  10. }
  11. ]
  12. }
  13. }
  14. }

连接值的数组

{{#join}}array{{/join}} 函数能用来将数组的值连接为以逗号分隔的字符串:

  1. GET /_search/template
  2. {
  3. "inline": {
  4. "query": {
  5. "match": {
  6. "emails": "{{#join}}emails{{/join}}"
  7. }
  8. }
  9. },
  10. "params": {
  11. "emails": [ "username@email.com", "lastname@email.com" ]
  12. }
  13. }

其呈现为:

  1. {
  2. "query" : {
  3. "match" : {
  4. "emails" : "username@email.com,lastname@email.com"
  5. }
  6. }
  7. }

该函数还可以接受一个自定义分隔符:

  1. GET /_search/template
  2. {
  3. "inline": {
  4. "query": {
  5. "range": {
  6. "born": {
  7. "gte" : "{{date.min}}",
  8. "lte" : "{{date.max}}",
  9. "format": "{{#join delimiter='||'}}date.formats{{/join delimiter='||'}}"
  10. }
  11. }
  12. }
  13. },
  14. "params": {
  15. "date": {
  16. "min": "2016",
  17. "max": "31/12/2017",
  18. "formats": ["dd/MM/yyyy", "yyyy"]
  19. }
  20. }
  21. }

呈现为:

  1. {
  2. "query" : {
  3. "range" : {
  4. "born" : {
  5. "gte" : "2016",
  6. "lte" : "31/12/2017",
  7. "format" : "dd/MM/yyyy||yyyy"
  8. }
  9. }
  10. }
  11. }

默认值

默认值被写成 {{var}}{{^var}}default{{/var}} 比如:

  1. {
  2. "inline": {
  3. "query": {
  4. "range": {
  5. "line_no": {
  6. "gte": "{{start}}",
  7. "lte": "{{end}}{{^end}}20{{/end}}"
  8. }
  9. }
  10. }
  11. },
  12. "params": { ... }
  13. }

此时 params{ “start”: 10, “end”: 15 } ,该查询可以呈现为:

  1. {
  2. "range": {
  3. "line_no": {
  4. "gte": "10",
  5. "lte": "15"
  6. }
  7. }
  8. }

但是,当 params{ “start”: 10 } 时, 该查询就会使用默认值作为 end :

  1. {
  2. "range": {
  3. "line_no": {
  4. "gte": "10",
  5. "lte": "20"
  6. }
  7. }
  8. }

条件语句

条件语句不能使用模板的 JSON 形式表示。相反,模板必须作为字符串传递。例如,假设我们想在 line 字段上运行 match 查询,并且可以选择用行号过滤其中 startend 是可选的。

参数(params)会像这样:

  1. {
  2. "params": {
  3. "text": "words to search for",
  4. "line_no": {
  5. "start": 10,
  6. "end": 20
  7. }
  8. }
  9. }

① 所有这三个元素都是可选的。

查询语句我们可以是:

  1. {
  2. "query": {
  3. "bool": {
  4. "must": {
  5. "match": {
  6. "line": "{{text}}"
  7. }
  8. },
  9. "filter": {
  10. {{#line_no}}
  11. "range": {
  12. "line_no": {
  13. {{#start}}
  14. "gte": "{{start}}"
  15. {{#end}},{{/end}}
  16. {{/start}}
  17. {{#end}}
  18. "lte": "{{end}}"
  19. {{/end}}
  20. }
  21. }
  22. {{/line_no}}
  23. }
  24. }
  25. }
  26. }

① 填充 text 参数值。

② 仅当指定 line_no 时才能包含 range 过滤器。

③ 仅当指定了line_no.start 时才能包含 gte 子句。

④ 填充 line_no.start 参数值。

⑤ 仅当 line_no.startline_no.end 被指定时,在 gte 子句后添加逗号。

⑦ 仅当指定 line_no.end 时,包含 lte 子句。

⑩ 填充 line_no.end 参数值。

注意

如上所述,模板不是有效的 JSON 形式,因为它包含类似 的部分标记,因此,模板应存储在文件中(参考 预注册模板 一节)或者在通过 REST API 使用时,应该将其写成字符串格式,比如:

  1. "inline": "{\"query\":{\"bool\":{\"must\":{\"match\":{\"line\":\"{{text}}\"}},\"filter\":{{{#line_no}}\"range\":{\"line_no\":{{{#start}}\"gte\":\"{{start}}\"{{#end}},{{/end}}{{/start}}{{#end}}\"lte\":\"{{end}}\"{{/end}}}}{{/line_no}}}}}}"

预注册(Pre-registered)模板

你可以通过将搜索模板存储在 config/scripts 目录中,在使用 .mustache 扩展名的文件中注册搜索模板。为了执行存储的模板,请使用 template 键下单名称来引用它:

  1. GET /_search/template
  2. {
  3. "file": "storedTemplate",
  4. "params": {
  5. "query_string": "search for these words"
  6. }
  7. }

config/sripts/ 查询模板的名称,即:

storedTemplate.mustache.

你还可以通过将搜索模板存储在集群状态中来注册搜索模板,由 REST API 来管理这些索引的模板。

  1. POST /_search/template/<templatename>
  2. {
  3. "template": {
  4. "query": {
  5. "match": {
  6. "title": "{{query_string}}"
  7. }
  8. }
  9. }
  10. }

该模板可以通过以下方法来检查:

  1. GET /_search/template/<templatename>

其可以呈现为:

  1. {
  2. "template": {
  3. "query": {
  4. "match": {
  5. "title": "{{query_string}}"
  6. }
  7. }
  8. }
  9. }

这个模板可以被删除:

  1. DELETE /_search/template/<templatename>

在搜索时使用索引模板,使用:

  1. GET /_search/template
  2. {
  3. "id": "templateName",
  4. "params": {
  5. "query_string": "search for these words"
  6. }
  7. }

① 存储在 .scripts 索引中的查询模板的名称。

验证(Validating)模板

  1. 可以在具有给定参数的响应中使用来呈现模板:
  1. GET /_render/template
  2. {
  3. "inline": {
  4. "query": {
  5. "terms": {
  6. "status": [
  7. "{{#status}}",
  8. "{{.}}",
  9. "{{/status}}"
  10. ]
  11. }
  12. }
  13. },
  14. "params": {
  15. "status": [ "pending", "published" ]
  16. }
  17. }

次调用将返回呈现的模板:

  1. {
  2. "template_output": {
  3. "query": {
  4. "terms": {
  5. "status": [
  6. "pending",
  7. "published"
  8. ]
  9. }
  10. }
  11. }
  12. }

① status 数据已使用来自 params 对象的值填充。

  1. 文件和索引模板也可以通过分别用 file id 代替 inline 来呈现。例如,呈现文件模板:
  1. GET /_render/template
  2. {
  3. "file": "my_template",
  4. "params": {
  5. "status": [ "pending", "published" ]
  6. }
  7. }

预注册模板可以使用以下呈现:

  1. GET /_render/template/<template_name>
  2. {
  3. "params": {
  4. "..."
  5. }
  6. }