Elasticsearch 提供一种高级的功能叫做 Search template,它的主要功能是将我们业务上复杂的逻辑进行模板化,隐藏查询逻辑,在查询的时候,只需要填入不同的值作为查询参数即可。这个概念可以和关系型数据库MySQL 中的存储过程相对应,预先定义好一个存储过程,调用的时候传入特定的参数即可。
使用 search teamplate 至少有如下优势
- 更容易测试和执行查询
- 避免重复构造查询,减少重复造车
- 通过预先定义的模板,限制用户的查询行为,只让他们执行一些预定义的查询
- 将搜索逻辑与应用程序逻辑分离
测试数据如下:
PUT user_info/_doc/2
{
"user": "liwangz",
"uid": 8,
"age": 20,
"city": "Beijing",
"skill": "bgda"
}
PUT user_info/_doc/1
{
"user": "rudonx",
"uid": 7,
"age": 18,
"city": "Shanghai",
"skill": "ana"
}
定义一个search template:在这里我们定义了两个参数,my_field 和 my_value
POST _scripts/myfirst_search_template
{
"script": {
"lang": "mustache",
"source": {
"query": {
"match": {
"{{para}}": "{{value}}"
}
}
}
}
}
调用查询模板:
GET user_info/_search/template
{
"id": "myfirst_search_template",
"params": {
"para": "skill",
"value": "bgda"
}
}
输出结果如下:
"hits" : [
{
"_index" : "user_info",
"_type" : "_doc",
"_id" : "2",
"_score" : 0.6931471,
"_source" : {
"user" : "liwangz",
"uid" : 8,
"age" : 20,
"city" : "Beijing",
"skill" : "bgda"
}
调用模板的查询相当于运行如下查询语句:在查询语句不复杂的时候,二者在复杂度方面差别不大,当查询较为复杂时候,search teamplate 的优势就较为明显了。
GET user_info/_search
{
"query": {
"match" : {
"city": "beijing"
}
}
}
从官方文档中的描述来看,使用 _msearch 同时调用多个 search teamplate,通常来说运行速度会快与每个单个运行
These requests often have less overhead and faster speeds than multiple individual searches
创建另外一个 template
POST _scripts/mySecond_search_template
{
"script": {
"lang": "mustache",
"source": {
"query": {
"match": {
"{{para1}}": "{{value1}}"
}
}
}
}
}
同时调用两个 template,会将两个文档同时输出
GET user_info/_msearch/template
{}
{"id":"myfirst_search_template","params":{"para":"skill","value":"bgda"}}
{}
{"id":"mySecond_search_template","params":{"para1":"city","value1":"Shanghai"}}
在 mustache 中,没有 if-else 的语法,我们只能通过 Sections 来实现。
如下定义一个 search teamplate,定义两个变量,query_city 和 query_age,如果查询语句匹配到 query_city,则跳入到query_age 的逻辑。如果查询匹配不到query_city,则整个逻辑结束。
POST _scripts/if_else_test
{
"script": {
"lang": "mustache",
"source": """
{
"query": {
"bool": {
"must": [
{
"match": {
"city": "{{query_city}}"
}
}
{{#age}}
,
{
"range": {
"age": {
"gte": {{query_age}}
}
}
}
{{/age}}
]
}
}
}
"""
}
}
进行查询,传入变量 Beijing,以及 20,这意味着先去匹配 city=Beijing, 匹配到之后,再去查找条件 age >=20 的数据。
GET user_info/_search/template
{
"id": "if_else_test",
"params": {
"query_city": "Beijing",
"query_age": "20"
}
}
查询一个 template
GET _scripts/<templateid>
删除一个 template
DELETE _scripts/<templateid>
设置默认值
设置默认值的语法为:
{{my-val}}{{^my-var}}default value{{/my-var}}
如下示例定义两个变量,my-var 和 my-val,默认值为city 和 Beijing:
POST _scripts/myThird_search_template
{
"script": {
"lang": "mustache",
"source": {
"query": {
"match": {
"{{my-var}}{{^my-var}}city{{/my-var}}": "{{my-val}}{{^my-val}}Beijing{{/my-val}}"
}
}
}
}
}
运行如下查询,我们不传入变量,查询语句会自动使用 search template 中的默认值。
GET user_info/_search/template
{
"id": "myThird_search_template"
}
[1] https://www.elastic.co/guide/en/elasticsearch/reference/7.17/search-template.html
如果您有其他问题,欢迎您联系火山引擎技术支持服务