正在加载

搜索模板

Elastic Stack Serverless

搜索模板是可使用不同变量运行的存储搜索。

如果将 Elasticsearch 用作搜索后端,则可以将搜索栏中的用户输入作为搜索模板的参数传递。 这样您就可以运行搜索,而无需向用户公开 Elasticsearch 的查询语法。

如果将 Elasticsearch 用于自定义应用程序,则搜索模板允许您更改搜索,而无需修改应用程序的代码。

要创建或更新搜索模板,请使用创建存储脚本 API

请求的 source 支持与搜索 API的请求正文相同的参数。source 还接受来自开源项目 mustache.javaMustache 变量。

通常,Mustache 变量包含在双花括号中:{{my-var}}。 运行模板化搜索时,Elasticsearch 会将这些变量替换为来自 params 的值。 要了解有关 mustache 语法的更多信息,请参见Mustache.js 手册 搜索模板必须使用 langmustache

以下请求创建 idmy-search-template 的搜索模板。

 PUT _scripts/my-search-template {
  "script": {
    "lang": "mustache",
    "source": {
      "query": {
        "match": {
          "message": "{{query_string}}"
        }
      },
      "from": "{{from}}",
      "size": "{{size}}"
    }
  }
}

Elasticsearch 将搜索模板作为 Mustache 脚本存储在群集状态中。 Elasticsearch 在 template 脚本上下文中编译搜索模板。 限制或禁用脚本的设置也会影响搜索模板。

要使用不同的 params 测试模板,请使用渲染搜索模板 API

 POST _render/template {
  "id": "my-search-template",
  "params": {
    "query_string": "hello world",
    "from": 20,
    "size": 10
  }
}

渲染后,该模板输出搜索请求正文

{
  "template_output": {
    "query": {
      "match": {
        "message": "hello world"
      }
    },
    "from": "20",
    "size": "10"
  }
}

您还可以使用 API 测试内联模板。

 POST _render/template {
    "source": {
      "query": {
        "match": {
          "message": "{{query_string}}"
        }
      },
      "from": "{{from}}",
      "size": "{{size}}"
    },
  "params": {
    "query_string": "hello world",
    "from": 20,
    "size": 10
  }
}

要使用搜索模板运行搜索,请使用搜索模板 API。 您可以在每个请求中指定不同的 params

 GET my-index/_search/template {
  "id": "my-search-template",
  "params": {
    "query_string": "hello world",
    "from": 0,
    "size": 10
  }
}

该响应使用与搜索 API的响应相同的属性。

{
  "took": 36,
  "timed_out": false,
  "_shards": {
    "total": 1,
    "successful": 1,
    "skipped": 0,
    "failed": 0
  },
  "hits": {
    "total": {
      "value": 1,
      "relation": "eq"
    },
    "max_score": 0.5753642,
    "hits": [
      {
        "_index": "my-index",
        "_id": "1",
        "_score": 0.5753642,
        "_source": {
          "message": "hello world"
        }
      }
    ]
  }
}

要使用单个请求运行多个模板化搜索,请使用多重搜索模板 API。 与多个单独的搜索相比,这些请求通常具有更少的开销和更快的速度。

 GET my-index/_msearch/template { }
{ "id": "my-search-template", "params": { "query_string": "hello world", "from": 0, "size": 10 }}
{ }
{ "id": "my-other-search-template", "params": { "query_type": "match_all" }}

要检索搜索模板,请使用获取存储脚本 API

 GET _scripts/my-search-template 

要获取所有搜索模板和其他存储脚本的列表,请使用群集状态 API

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

要删除搜索模板,请使用删除存储脚本 API

 DELETE _scripts/my-search-template 

要为变量设置默认值,请使用以下语法

{{my-var}}{{^my-var}}default value{{/my-var}}

如果模板化搜索未在其 params 中指定值,则搜索将改用默认值。 例如,以下模板为 fromsize 设置默认值。

 POST _render/template {
  "source": {
    "query": {
      "match": {
        "message": "{{query_string}}"
      }
    },
    "from": "{{from}}{{^from}}0{{/from}}",
    "size": "{{size}}{{^size}}10{{/size}}"
  },
  "params": {
    "query_string": "hello world"
  }
}

使用 {{#url}} 函数对字符串进行 URL 编码。

 POST _render/template {
  "source": {
    "query": {
      "term": {
        "url.full": "{{#url}}{{host}}/{{page}}{{/url}}"
      }
    }
  },
  "params": {
    "host": "http://example.com",
    "page": "hello-world"
  }
}

该模板呈现为

{
  "template_output": {
    "query": {
      "term": {
        "url.full": "http%3A%2F%2Fexample.com%2Fhello-world"
      }
    }
  }
}

使用 {{#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"
      }
    }
  }
}

您还可以指定自定义分隔符。

 POST _render/template {
  "source": {
    "query": {
      "range": {
        "user.effective.date": {
          "gte": "{{date.min}}",
          "lte": "{{date.max}}",
          "format": "{{#join delimiter='||'}}date.formats{{/join delimiter='||'}}"
	      }
      }
    }
  },
  "params": {
    "date": {
      "min": "2098",
      "max": "06/05/2099",
      "formats": ["dd/MM/yyyy", "yyyy"]
    }
  }
}

该模板呈现为

{
  "template_output": {
    "query": {
      "range": {
        "user.effective.date": {
          "gte": "2098",
          "lte": "06/05/2099",
          "format": "dd/MM/yyyy||yyyy"
        }
      }
    }
  }
}

使用 {{#toJson}} 函数将变量值转换为其 JSON 表示形式。

例如,以下模板使用 {{#toJson}} 传递一个数组。 为确保请求正文是有效的 JSON,source 以字符串格式编写。

 POST _render/template {
  "source": "{ \"query\": { \"terms\": { \"tags\": {{#toJson}}tags{{/toJson}} }}}",
  "params": {
    "tags": [
      "prod",
      "es01"
    ]
  }
}

该模板呈现为

{
  "template_output": {
    "query": {
      "terms": {
        "tags": [
          "prod",
          "es01"
        ]
      }
    }
  }
}

您还可以使用 {{#toJson}} 传递对象。

 POST _render/template {
  "source": "{ \"query\": {{#toJson}}my_query{{/toJson}} }",
  "params": {
    "my_query": {
      "match_all": { }
    }
  }
}

该模板呈现为

{
  "template_output" : {
    "query" : {
      "match_all" : { }
    }
  }
}

您还可以传递对象数组。

 POST _render/template {
  "source": "{ \"query\": { \"bool\": { \"must\": {{#toJson}}clauses{{/toJson}} }}}",
  "params": {
    "clauses": [
      {
        "term": {
          "user.id": "kimchy"
        }
      },
      {
        "term": {
          "url.domain": "example.com"
        }
      }
    ]
  }
}

该模板呈现为

{
  "template_output": {
    "query": {
      "bool": {
        "must": [
          {
            "term": {
              "user.id": "kimchy"
            }
          },
          {
            "term": {
              "url.domain": "example.com"
            }
          }
        ]
      }
    }
  }
}

要创建 if 条件,请使用以下语法

{{#condition}}content{{/condition}}

如果条件变量为 true,则 Elasticsearch 会显示其内容。 例如,如果 year_scopetrue,则以下模板会搜索过去一年的数据。

 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_scopefalse,则该模板会搜索任何时间段的数据。

 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": false,
    "user_id": "kimchy"
  }
}

该模板呈现为

{
  "template_output" : {
    "query" : {
      "bool" : {
        "filter" : [
          {
            "term" : {
              "user.id" : "kimchy"
            }
          }
        ]
      }
    }
  }
}

要创建 if-else 条件,请使用以下语法

{{#condition}}if content{{/condition}} {{^condition}}else content{{/condition}}

例如,如果 year_scopetrue,则以下模板会搜索过去一年的数据。 否则,它会搜索过去一天的数据。

 POST _render/template {
  "source": "{ \"query\": { \"bool\": { \"filter\": [ { \"range\": { \"@timestamp\": { \"gte\": {{#year_scope}} \"now-1y/d\" {{/year_scope}} {{^year_scope}} \"now-1d/d\" {{/year_scope}} , \"lt\": \"now/d\" }}}, { \"term\": { \"user.id\": \"{{user_id}}\" }}]}}}",
  "params": {
    "year_scope": true,
    "user_id": "kimchy"
  }
}

mustache 模板语言定义了您可以在模板中使用的各种标记类型。 以下各节描述了其中一些标记类型,并提供了在 Elasticsearch 搜索模板中使用它们的示例。

Mustache 标记通常包含在双花括号中。 mustache 变量:{{my-variable}} 是一种 mustache 标记。 运行模板化搜索时,Elasticsearch 会将这些变量替换为来自 params 的值。

例如,考虑以下搜索模板

 PUT _scripts/my-search-template {
  "script": {
    "lang": "mustache",
    "source": {
      "query": {
        "match": {
          "message": "{{query_string}}"
        }
      },
      "from": "{{from}}",
      "size": "{{size}}"
    }
  }
}

使用 params 测试上述搜索模板

 POST _render/template {
  "id": "my-search-template",
  "params": {
    "query_string": "hello world",
    "from": 20,
    "size": 10
  }
}

渲染后,message 中的 {{query_string}} 将替换为 params 中传递的 hello world

{
  "template_output": {
    "query": {
      "match": {
        "message": "hello world"
      }
    },
    "from": "20",
    "size": "10"
  }
}

如果您的搜索模板未将值传递给您的 query_string,则该消息将被替换为空字符串。

例如

 POST _render/template {
  "id": "my-search-template",
  "params": {
    "from": 20,
    "size": 10
  }
}

渲染后,模板输出为

{
  "template_output": {
    "query": {
      "match": {
        "message": ""
      }
    },
    "from": "20",
    "size": "10"
  }
}

区段也是 Mustache 标记的一种类型。 您可以在搜索模板中使用带有嵌套或未嵌套对象的 sections。 区段以 {{#my-section-variable}} 开头,以 {{/my-section-variable}} 结尾。

以下搜索模板显示了一个使用带有嵌套对象的区段的示例

 POST _render/template {
  "source":
  """
  {
    "query": {
      "match": {
        {{#query_message}}
          {{#query_string}}
        "message": "Hello {{#first_name_section}}{{first_name}}{{/first_name_section}} {{#last_name_section}}{{last_name}}{{/last_name_section}}"
          {{/query_string}}
        {{/query_message}}
      }
    }
  }
  """,
  "params": {
    "query_message": {
       "query_string": {
         "first_name_section": {"first_name": "John"},
         "last_name_section": {"last_name": "kimchy"}
       }
    }
  }
}

该模板呈现为

{
  "template_output": {
    "query": {
      "match": {
        "message": "Hello John kimchy"
      }
    }
  }
}

您可以传递一个对象列表,并在搜索模板中循环访问每个项目。

例如,以下搜索模板结合了区段并匹配所有用户名

 PUT _scripts/my-search-template {
  "script": {
    "lang": "mustache",
    "source": {
      "query":{
        "multi_match":{
          "query": "{{query_string}}",
          "fields": """[{{#text_fields}}{{user_name}},{{/text_fields}}]"""
        }
      }
    }
  }
}

测试模板

 POST _render/template {
  "id": "my-search-template",
  "params": {
    "query_string": "My string",
    "text_fields": [
      {
        "user_name": "John"
      },
      {
        "user_name": "kimchy"
      }
    ]
  }
}

渲染后,模板输出

{
  "template_output": {
    "query": {
      "multi_match": {
        "query": "My string",
        "fields": "[John,kimchy,]"
      }
    }
  }
}
注意

以上操作会导致尾随逗号问题,从而导致 JSON 无效。 一种解决方法是包括一个反向区段并添加一个变量以确保它是数组中的最后一个项目。

例如

 PUT _scripts/my-search-template {
  "script": {
    "lang": "mustache",
    "source": {
      "query":{
        "multi_match":{
          "query": "{{query_string}}",
          "fields": """[{{#text_fields}}{{user_name}}{{^last}},{{/last}}{{/text_fields}}]"""
        }
      }
    }
  }
}

再次使用变量 last 测试 my-search-template 以确定它是否是数组中的最后一个项目

 POST _render/template {
  "id": "my-search-template",
  "params": {
    "query_string": "My string",
    "text_fields": [
      {
        "user_name": "John",
        "last": false
      },
      {
        "user_name": "kimchy",
        "last": true
      }
    ]
  }
}

渲染后,模板输出

{
  "template_output": {
    "query": {
      "multi_match": {
        "query": "My string",
        "fields": "[John,kimchy]"
      }
    }
  }
}

Elasticsearch 具有预构建的自定义函数,以支持将文本转换为特定格式。

要了解有关 mustache lambdas 的用法的更多信息,请查看Url 编码字符串连接值转换为 json中的示例。

当您只想设置一次值时,反向区段很有用。

要使用反向区段,请使用以下语法

{{^my-variable}} content {{/my-variable}}

例如,在以下搜索模板中,如果 name_existsfalse,则 message 设置为 Hello World,否则它将设置为空字符串。

 POST _render/template {
  "source": {
    "query": {
      "match": {
        "message": "{{^name_exists}}Hello World{{/name_exists}}"
      }
    }
  },
  "params": {
     "name_exists": false
  }
}

它们也可以与条件默认值结合使用。

例如,在以下搜索模板中,如果 name_existstrue,则替换 {{query_string}} 的值。 如果 name_existsfalse,则将其设置为默认值 World

 POST _render/template {
  "source": {
    "query": {
      "match": {
        "message": "Hello {{#name_exists}}{{query_string}}{{/name_exists}}{{^name_exists}}World{{/name_exists}}"
      }
    }
  },
  "params": {
    "query_string": "Kimchy",
     "name_exists": true
  }
}

渲染后,模板输出

{
  "template_output": {
    "query": {
      "match": {
        "message": "Hello Kimchy"
      }
    }
  }
}

您可以将默认分隔符:双花括号 {{my-variable}} 更改为搜索模板中的任何自定义分隔符。

例如,以下搜索模板将默认分隔符更改为单个圆括号 (query_string)

 PUT _scripts/my-search-template {
  "script": {
    "lang": "mustache",
    "source":
    """
    {
      "query": {
        "match": {
           {{=( )=}}
          "message": "(query_string)"
          (={{ }}=)
        }
      }
    }
    """
  }
}

使用新分隔符测试模板

 POST _render/template {
  "id": "my-search-template",
  "params": {
    "query_string": "hello world"
  }
}

渲染后,模板输出

{
  "template_output": {
    "query": {
      "match": {
        "message": "hello world"
      }
    }
  }
}

以下 mustache 功能在 Elasticsearch 搜索模板中不受支持

  • 局部视图
© . All rights reserved.