Link Search Menu Expand Document Documentation Menu

搜索模板

您可以将全文查询转换为搜索模板,以接受用户输入并将其动态插入到查询中。

例如,如果您使用 OpenSearch 作为您的应用程序或网站的后端搜索引擎,您可以从搜索栏或表单字段获取用户查询,并将其作为参数传递到搜索模板中。这样,创建 OpenSearch 查询的语法就对您的最终用户进行了抽象。

在编写将用户输入转换为 OpenSearch 查询的代码时,您可以使用搜索模板来简化代码。如果需要向搜索查询添加字段,只需修改模板即可,无需更改代码。

搜索模板使用 Mustache 语言。有关所有语法选项的列表,请参阅 Mustache 手册

创建搜索模板

搜索模板有两个组成部分:查询和参数。参数是用户输入的值,它们被放入变量中。变量在 Mustache 符号中用双大括号表示。当在查询中遇到类似 {{var}} 的变量时,OpenSearch 会转到 params 部分,查找名为 var 的参数,并将其替换为指定的值。

您可以编写应用程序代码,询问用户他们想要搜索什么,然后在运行时将该值插入到 params 对象中。

此命令定义了一个搜索模板,用于按剧名查找剧本。查询中的 {{play_name}} 被值 Henry IV 替换。

GET _search/template
{
  "source": {
    "query": {
      "match": {
        "play_name": "{{play_name}}"
      }
    }
  },
  "params": {
    "play_name": "Henry IV"
  }
}

此模板在整个集群上运行搜索。要在特定索引上运行此搜索,请将索引名称添加到请求中。

GET shakespeare/_search/template

指定 fromsize 参数

GET _search/template
{
  "source": {
    "from": "{{from}}",
    "size": "{{size}}",
    "query": {
      "match": {
        "play_name": "{{play_name}}"
      }
    }
  },
  "params": {
    "play_name": "Henry IV",
    "from": 10,
    "size": 10
  }
}

为了改善搜索体验,您可以定义默认值,这样用户就不必指定所有可能的参数。如果 params 部分未定义参数,OpenSearch 将使用默认值。

定义变量 var 默认值的语法如下:

{{var}}{{^var}}default value{{/var}}

此命令将 from 的默认值设置为 10,将 size 的默认值设置为 10。

GET _search/template
{
  "source": {
    "from": "{{from}}{{^from}}10{{/from}}",
    "size": "{{size}}{{^size}}10{{/size}}",
    "query": {
      "match": {
        "play_name": "{{play_name}}"
      }
    }
  },
  "params": {
    "play_name": "Henry IV"
  }
}

保存并执行搜索模板

在搜索模板按照您希望的方式工作后,您可以将该模板的源保存为脚本,使其可以重复用于不同的输入参数。

将搜索模板保存为脚本时,需要将 lang 参数指定为 mustache

POST _scripts/play_search_template
{
  "script": {
    "lang": "mustache",
    "source": {
      "from": "{{from}}{{^from}}0{{/from}}",
      "size": "{{size}}{{^size}}10{{/size}}",
      "query": {
        "match": {
          "play_name": "{{play_name}}"
        }
      }
    },
    "params": {
      "play_name": "Henry IV"
    }
  }
}

现在,您可以通过引用其 id 参数来重用模板。您可以将此源模板重用于不同的输入值。

GET _search/template
{
  "id": "play_search_template",
  "params": {
    "play_name": "Henry IV",
    "from": 0,
    "size": 1
  }
}

示例响应

{
  "took": 7,
  "timed_out": false,
  "_shards": {
    "total": 6,
    "successful": 6,
    "skipped": 0,
    "failed": 0
  },
  "hits": {
    "total": {
      "value": 3205,
      "relation": "eq"
    },
    "max_score": 3.641852,
    "hits": [
      {
        "_index": "shakespeare",
        "_type": "_doc",
        "_id": "4",
        "_score": 3.641852,
        "_source": {
          "type": "line",
          "line_id": 5,
          "play_name": "Henry IV",
          "speech_number": 1,
          "line_number": "1.1.2",
          "speaker": "KING HENRY IV",
          "text_entry": "Find we a time for frighted peace to pant,"
        }
      }
    ]
  }
}

如果您有存储的模板并希望验证它,请使用 render 操作。

POST _render/template
{
  "id": "play_search_template",
  "params": {
    "play_name": "Henry IV"
  }
}

有关更多信息,请参阅 渲染模板 API

使用搜索模板进行高级参数转换

Mustache 中有许多不同的语法选项,可以将输入参数转换为查询。您可以指定条件、运行循环、连接数组、将数组转换为 JSON 等等。

条件

在 Mustache 中使用 section 标签表示条件

{{#var}}var{{/var}}

var 是一个布尔值时,此语法充当 if 条件。{{#var}}{{/var}} 标签仅当 var 评估为 true 时才插入它们之间的值。

使用 section 标签会使您的 JSON 无效,因此您必须以字符串格式编写查询。

此命令仅在 limit 参数设置为 true 时才在查询中包含 size 参数。在以下示例中,limit 参数为 true,因此 size 参数被激活。结果,您将只获得两个文档。

GET _search/template
{
  "source": "{ {{#limit}} \"size\": \"{{size}}\", {{/limit}}  \"query\":{\"match\":{\"play_name\": \"{{play_name}}\"}}}",
  "params": {
    "play_name": "Henry IV",
    "limit": true,
    "size": 2
  }
}

您还可以设计一个 if-else 条件。如果 limittrue,此命令将 size 设置为 2。否则,它将 size 设置为 10

GET _search/template
{
  "source": "{ {{#limit}} \"size\": \"2\", {{/limit}} {{^limit}} \"size\": \"10\", {{/limit}} \"query\":{\"match\":{\"play_name\": \"{{play_name}}\"}}}",
  "params": {
    "play_name": "Henry IV",
    "limit": true
  }
}

循环

您还可以使用 section 标签来实现 for-each 循环

{{#var}}{{.}}{{/var}}

var 是一个数组时,搜索模板会遍历它并创建一个 terms 查询。

GET _search/template
{
  "source": "{\"query\":{\"terms\":{\"play_name\":[\"{{#play_name}}\",\"{{.}}\",\"{{/play_name}}\"]}}}",
  "params": {
    "play_name": [
      "Henry IV",
      "Othello"
    ]
  }
}

此模板呈现为

GET _search/template
{
  "source": {
    "query": {
      "terms": {
        "play_name": [
          "Henry IV",
          "Othello"
        ]
      }
    }
  }
}

连接

您可以使用 join 标签来连接数组的值(用逗号分隔)

GET _search/template
{
  "source": {
    "query": {
      "match": {
        "text_entry": "{{#join}}{{text_entry}}{{/join}}"
      }
    }
  },
  "params": {
    "text_entry": [
      "To be",
      "or not to be"
    ]
  }
}

呈现为

GET _search/template
{
  "source": {
    "query": {
      "match": {
        "text_entry": "{0=To be, 1=or not to be}"
      }
    }
  }
}

转换为 JSON

您可以使用 toJson 标签将参数转换为其 JSON 表示形式

GET _search/template
{
  "source": "{\"query\":{\"bool\":{\"must\":[{\"terms\": {\"text_entries\": {{#toJson}}text_entries{{/toJson}} }}] }}}",
  "params": {
    "text_entries": [
        { "term": { "text_entry" : "love" } },
        { "term": { "text_entry" : "soldier" } }
    ]
  }
}

呈现为

GET _search/template
{
  "source": {
    "query": {
      "bool": {
        "must": [
          {
            "terms": {
              "text_entries": [
                {
                  "term": {
                    "text_entry": "love"
                  }
                },
                {
                  "term": {
                    "text_entry": "soldier"
                  }
                }
              ]
            }
          }
        ]
      }
    }
  }
}

多个搜索模板

您可以使用 msearch 操作将多个搜索模板捆绑在一起,并在单个请求中发送到 OpenSearch 集群。这可以节省网络往返时间,与独立请求相比,您可以更快地获得响应。

GET _msearch/template
{"index":"shakespeare"}
{"id":"if_search_template","params":{"play_name":"Henry IV","limit":false,"size":2}}
{"index":"shakespeare"}
{"id":"play_search_template","params":{"play_name":"Henry IV"}}

有关更多信息,请参阅 多搜索模板 API

管理搜索模板

要列出所有脚本,请运行以下命令:

GET _cluster/state/metadata?pretty&filter_path=**.stored_scripts

要检索特定搜索模板,请运行以下命令:

GET _scripts/<name_of_search_template>

要删除搜索模板,请运行以下命令:

DELETE _scripts/<name_of_search_template>


相关文章