原文链接:https://xiets.blog.csdn.net/article/details/144221801
版权声明:原创文章禁止转载
搜索模板相关链接:
搜索模板是一个存储搜索,用户可以使用不同的参数运行。对于一些逻辑复杂的查询,可以先把查询逻辑封装为一个搜索模板,然后只需要传入不同的参数就能搜索出不同的结果。
1. 创建/获取/验证搜索模板
创建或更新搜索模板,需要使用创建存储脚本API:Create or update stored script API。此 API 不仅可以创建搜索模板,还可以创建 Painless 脚本。
1.1 创建/修改搜索模板
创建/修改搜索模板:
PUT /_scripts/my-search-template // 创建/修改脚本, 指定 脚本ID (搜索模板ID), 这里指定的模板ID为 "my-search-template"
{
"script": {
"lang": "mustache", // 脚本语言类型, 搜索模板 使用 "mustache"
"source": { // (对象 或 字符串) 模板内容 (运行搜索模板时将作为搜索请求的Body)
"from": "{{from}}", // 以双大括号 {{param}} 的方式引用参数
"size": "{{size}}",
"query": {
"match": {
"message": "{{query_string}}"
}
}
}
}
}
// 搜索模板 的 脚本内容(source), 可以以对象的方式提供, 也可以把对象序列化为字符串提供。
// 如果 source 提供的是对象, 则会把对象序列化为字符串存储。
// 执行搜索时, 应用了实际参数的 source 将作为搜索请求的 Body。
1.2 获取搜索模板
要获取搜索模板,请使用获取存储脚本的API:Get stored script API。
获取搜索模板:
GET /_scripts/my-search-template
// 返回
{
"_id" : "my-search-template",
"found" : true,
"script" : {
"lang" : "mustache",
"source" : "{\"from\":\"{{from}}\",\"size\":\"{{size}}\",\"query\":{\"match\":{\"message\":\"{{query_string}}\"}}}",
"options" : {
"content_type" : "application/json;charset=utf-8"
}
}
}
要获取所有搜索模板和其他存储脚本的列表,请使用集群状态API:Cluster state API。
获取所有存储的脚本:
GET /_cluster/state/metadata?pretty&filter_path=metadata.stored_scripts
// 返回
{
"metadata" : {
"stored_scripts" : {
"my-search-template" : {
"lang" : "mustache",
"source" : "{\"from\":\"{{from}}\",\"size\":\"{{size}}\",\"query\":{\"match\":{\"message\":\"{{query_string}}\"}}}",
"options" : {
"content_type" : "application/json;charset=utf-8"
}
},
"search_hotel" : {
"lang" : "mustache",
"source" : "{\"query\":{\"bool\":{\"must\":[{\"match\":{\"name\":\"{{query_string}}\"}},{\"range\":{\"price\":{\"lte\":\"{{max_price}}\"}}}]}}}",
"options" : {
"content_type" : "application/json;charset=utf-8"
}
}
}
}
}
1.3 验证搜索模板
要测试搜索模板在搜索请求时的具体请求Body,可以用渲染搜索模板API:render search template API。
验证搜索模板:
POST /_render/template
{
"id": "my-search-template", // 指定搜索模板ID
"params": { // 传递参数
"from": 20,
"size": 10,
"query_string": "Hello World"
}
}
// 返回
{
"template_output": { // 此对象将作为搜索请求的Body
"from": "20",
"size": "10",
"query": {
"match": {
"message": "Hello World"
}
}
}
}
还可以使用渲染 API 测试内联模板(不指定模板ID,而是直接给出模板内容):
POST /_render/template
{
"source": { // 模板内容 (对象 或 字符串)
"query": {
"match": {
"message": "{{query_string}}"
}
},
"from": "{{from}}",
"size": "{{size}}"
},
"params": {
"query_string": "Hello World",
"from": 20,
"size": 10
}
}
// 返回
{
"template_output": {
"query": {
"match": {
"message": "Hello World"
}
},
"from": "20",
"size": "10"
}
}
1.4 删除模板
删除模板:
DELETE /_scripts/my-search-template
2. 模板参数
搜索模板的参数以双大括号 {{param}}
的形式引用,可以设置默认值、对字符串进行URL编码、传递 JSON 对象/数组类型的参数、连接数组值、使用条件判断 等。
2.1 参数默认值
要设置参数的默认值,使用以下语法:
{{param}}{{^param}}default_value{{/param}}
运行搜索模板时,如果没有传递参数值,则使用默认值:
POST /_render/template
{
"source": {
"from": "{{from}}{{^from}}0{{/from}}",
"size": "{{size}}{{^size}}10{{/size}}",
"query": {
"match": {
"message": "{{query_string}}"
}
}
},
"params": {
"query_string": "Hello World"
}
}
// 返回
{
"template_output": {
"from": "0",
"size": "10",
"query": {
"match": {
"message": "Hello World"
}
}
}
}
2.2 URL 编码字符串
搜索模板脚本可以使用内置的函数,使用函数的语法:
{{#function}}argument{{/function}}
使用 {{#url}}
函数对字符串进行 URL 编码:
POST /_render/template
{
"source": {
"query": {
"term": {
"url.full": "{{#url}}{{host}}/{{page}}{{/url}}"
}
}
},
"params": {
"host": "https://xiets.blog.csdn.net",
"page": "article/details/131849457"
}
}
// 返回
{
"template_output": {
"query": {
"term": {
"url.full": "https%3A%2F%2Fxiets.blog.csdn.net%2Farticle%2Fdetails%2F131849457"
}
}
}
}
2.3 JSON 对象/数组参数
使用 {{#toJson}}
函数可以将变量值转换为其 JSON 表示形式,为了确保请求 Body 是有效的 JSON,source 以字符串格式编写:
POST /_render/template
{
"source": "{ \"query\": { \"terms\": { \"tags\": {{#toJson}}tags{{/toJson}} } }, \"from\": {{from}}, \"size\": {{size}} }",
"params": {
"from": 0,
"size": 10,
"tags": [ "hello", "world" ]
}
}
// 返回
{
"template_output": {
"query": {
"terms": {
"tags": [ "hello", "world" ]
}
},
"from": 0,
"size": 10
}
}
2.4 连接数组值
使用 {{#join}}
函数将数组值连接为逗号,
分隔的字符串。例如,以下模板连接两个电子邮件地址:
POST /_render/template
{
"source": {
"query": {
"match": {
"user.group.emails": "{{#join}}emails{{/join}}"
}
}
},
"params": {
"emails": [ "user1@example.com", "user_one@example.com" ]
}
}
// 返回
{
"template_output": {
"query": {
"match": {
"user.group.emails": "user1@example.com,user_one@example.com"
}
}
}
}
2.5 使用条件判断
要创建 if 条件,请使用以下语法:
{{#condition}}content{{/condition}}
上面的 condition 是布尔类型的参数,如果此参数的值为 true
则显示内容(content),否则不显示内容。
POST /_render/template
{
"source": "{ \"query\": { \"bool\": { \"filter\": [ {{#year_scope}} { \"range\": { \"@timestamp\": { \"gte\": \"now-1y/d\", \"lt\": \"now/d\" } } }, {{/year_scope}} { \"term\": { \"user.id\": \"{{user_id}}\" }}]}}}",
"params": {
"year_scope": true,
"user_id": "kimchy"
}
}
// 返回
{
"template_output": {
"query": {
"bool": {
"filter": [
{
"range": {
"@timestamp": {
"gte": "now-1y/d",
"lt": "now/d"
}
}
},
{
"term": {
"user.id": "kimchy"
}
}
]
}
}
}
}
// 如果 "year_scope" 传递 false, 则返回
{
"template_output": {
"query": {
"bool": {
"filter": [
{
"term": {
"user.id": "kimchy"
}
}
]
}
}
}
}
3. 运行搜索模板
要使用搜索模板运行搜索,请使用搜索模板 API:Search template API,用户可以 params
为每个请求指定不同的参数内容。
运行搜索模板请求格式:
POST /<index>/_search/template // 指定在哪个索引中运行搜索模板
{
"id": "<template_id>", // 模板ID
"params": { // 传递参数
"from": 0,
"size": 10,
"query_string": "hello world"
}
}
为方便演示,下面创建示例索引和文档:
// 创建索引
PUT /hotel
{
"mappings": {
"properties": {
"name": {
"type": "text"
},
"price": {
"type": "double"
}
}
}
}
// 写入一些文档
PUT /hotel/_doc/001
{"name": "龙门国际大酒店", "price": 300.00}
PUT /hotel/_doc/002
{"name": "龙门精选假日酒店", "price": 200.00}
PUT /hotel/_doc/003
{"name": "龙门客栈古风酒店", "price": 350.00}
PUT /hotel/_doc/004
{"name": "悦来时尚宾馆", "price": 99.00}
PUT /hotel/_doc/005
{"name": "悦来文雅大酒店", "price": 550.00}
PUT /hotel/_doc/006
{"name": "烟雨楼文雅假日酒店", "price": 600.00}
创建搜索模板:
PUT /_scripts/search_hotel
{
"script": {
"lang": "mustache",
"source": {
"query": {
"bool": {
"must": [
{
"match": {
"name": "{{query_string}}"
}
},
{
"range": {
"price": {
"lte": "{{max_price}}"
}
}
}
]
}
}
}
}
}
查询模板:
GET /_scripts/search_hotel
// 返回
{
"_id" : "search_hotel",
"found" : true,
"script" : {
"lang" : "mustache",
"source" : "{\"query\":{\"bool\":{\"must\":[{\"match\":{\"name\":\"{{query_string}}\"}},{\"range\":{\"price\":{\"lte\":\"{{max_price}}\"}}}]}}}",
"options" : {
"content_type" : "application/json;charset=utf-8"
}
}
}
运行模板:
POST /hotel/_search/template
{
"id": "search_hotel",
"params": {
"query_string": "龙门",
"max_price": 300
}
}
// 返回
{
// ...,
"hits": {
"total": {
"value": 2,
"relation": "eq"
},
"max_score": 2.4251623,
"hits": [
{
"_index": "hotel",
"_id": "001",
"_score": 2.4251623,
"_source": {
"name": "龙门国际大酒店",
"price": 300
}
},
{
"_index": "hotel",
"_id": "002",
"_score": 2.3494902,
"_source": {
"name": "龙门精选假日酒店",
"price": 200
}
}
]
}
}