如何使用 Elasticsearch 中的 search template

前言

Elasticsearch 提供一种高级的功能叫做 Search template,它的主要功能是将我们业务上复杂的逻辑进行模板化,隐藏查询逻辑,在查询的时候,只需要填入不同的值作为查询参数即可。这个概念可以和关系型数据库MySQL 中的存储过程相对应,预先定义好一个存储过程,调用的时候传入特定的参数即可。

使用 search template 的优势

使用 search teamplate 至少有如下优势

  • 更容易测试和执行查询
  • 避免重复构造查询,减少重复造车
  • 通过预先定义的模板,限制用户的查询行为,只让他们执行一些预定义的查询
  • 将搜索逻辑与应用程序逻辑分离
如何定义一个search template

测试数据如下:

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" 
    } 
  }
}
同时调用多个search template

从官方文档中的描述来看,使用 _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"
  }
}
其他一些 API

查询一个 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

如果您有其他问题,欢迎您联系火山引擎技术支持服务

0
0
0
0
评论
未登录
看完啦,登录分享一下感受吧~
暂无评论