【Elasticsearch】检索模板(Search Template)

Elasticsearch 检索》系列,共包含以下文章:

😊 如果您觉得这篇文章有用 ✔️ 的话,请给博主一个一键三连 🚀🚀🚀 吧 (点赞 🧡、关注 💛、收藏 💚)!!!您的支持 💖💖💖 将激励 🔥 博主输出更多优质内容!!!

1.什么是检索模板

Elasticsearch 检索模板(Search Template)是一种预定义的搜索查询模板,使用 Mustache 模板语言编写。它允许你将查询逻辑与参数分离,使搜索查询更加动态和可重用。

2.应用场景和优势

2.1 应用场景

  • 标准化查询:为团队提供统一的查询结构。
  • 参数化搜索:允许用户输入不同参数获取不同结果。
  • 复杂查询简化:隐藏复杂查询逻辑,提供简单接口。
  • 权限控制:限制用户可以执行的查询类型。

2.2 优势

  • 安全性:避免暴露查询逻辑细节。
  • 可维护性:集中管理查询,一处修改多处生效。
  • 灵活性:支持动态参数注入。
  • 性能优化:预编译模板提高执行效率。

3.实际案例

3.1 准备测试数据

创建 products 索引并添加数据。

PUT products
{
  "mappings": {
    "properties": {
      "name": {"type": "text"},
      "price": {"type": "integer"},
      "category": {"type": "keyword"},
      "on_sale": {"type": "boolean"}
    }
  }
}

POST _bulk
{"index":{"_index":"products","_id":1}}
{"name":"华为手机 P40","price":3999,"category":"电子产品","on_sale":true}
{"index":{"_index":"products","_id":2}}
{"name":"小米手机 10","price":2999,"category":"电子产品","on_sale":false}
{"index":{"_index":"products","_id":3}}
{"name":"苹果手机 iPhone 12","price":5999,"category":"电子产品","on_sale":true}
{"index":{"_index":"products","_id":4}}
{"name":"联想笔记本电脑","price":4599,"category":"电子产品","on_sale":false}
{"index":{"_index":"products","_id":5}}
{"name":"耐克运动鞋","price":899,"category":"服装鞋帽","on_sale":true}
{"index":{"_index":"products","_id":6}}
{"name":"手机支架","price":59,"category":"配件","on_sale":true}

创建 blognews 索引并添加数据。

PUT blog
{
  "mappings": {
    "properties": {
      "title": {"type": "text"},
      "content": {"type": "text"},
      "created_at": {"type": "date"}
    }
  }
}

PUT news
{
  "mappings": {
    "properties": {
      "title": {"type": "text"},
      "content": {"type": "text"},
      "created_at": {"type": "date"}
    }
  }
}

POST _bulk
{"index":{"_index":"blog","_id":1}}
{"title":"Elasticsearch 入门指南","content":"本文介绍Elasticsearch的基本概念和使用方法","created_at":"2023-01-15"}
{"index":{"_index":"blog","_id":2}}
{"title":"Kibana 可视化教程","content":"学习如何使用Kibana创建Elasticsearch数据的可视化","created_at":"2023-02-20"}
{"index":{"_index":"news","_id":1}}
{"title":"Elasticsearch 8.0 发布","content":"Elastic公司发布了Elasticsearch 8.0版本,带来多项新特性","created_at":"2023-03-10"}
{"index":{"_index":"news","_id":2}}
{"title":"大数据技术趋势","content":"分析2023年大数据领域的技术趋势,包括Elasticsearch的应用","created_at":"2023-04-05"}

3.2 案例 1:基础检索模板

POST _scripts/product_search_template
{
  "script": {
    "lang": "mustache",
    "source": {
      "query": {
        "bool": {
          "must": [
            {"match": {"name": "{{query_string}}"} },
            {"range": {"price": {"gte": "{{min_price}}", "lte": "{{max_price}}"}}}
          ]
        }
      },
      "size": "{{size}}"
    }
  }
}

这段代码创建了一个名为 product_search_template 的 Elasticsearch 检索模板,其核心功能是:

动态搜索商品,支持以下参数化条件:

  1. 按名称模糊匹配query_string 参数)
  2. 按价格范围过滤min_pricemax_price 参数)
  3. 控制返回结果数量size 参数)

本质:将固定查询逻辑模板化,后续只需传递不同参数(如搜索关键词、价格区间)即可复用该查询结构,避免重复编写复杂 DSL。

典型应用场景:电商商品列表页的筛选查询(如搜索 “手机” 且价格在 2000~3000 元之间的商品)。

在这里插入图片描述

执行模板:

GET products/_search/template
{
  "id": "product_search_template",
  "params": {
    "query_string": "手机",
    "min_price": 2000,
    "max_price": 3000,
    "size": 10
  }
}

在这里插入图片描述

3.3 案例 2:带条件的模板

POST _scripts/conditional_search_template
{
  "script": {
    "lang": "mustache",
    "source": {
      "query": {
        "bool": {
          "must": [
            {
              "{{#is_on_sale}}": {
                "term": {"on_sale": true}
              }
            },
            {"match": {"category": "{{category}}"}}
          ]
        }
      }
    }
  }
}

这段代码定义了一个名为 conditional_search_template 的 Elasticsearch 动态检索模板,其核心特点是:

条件化商品搜索,包含以下逻辑:

  1. 可选条件:根据参数 is_on_sale 决定是否筛选「促销商品」(on_sale=true
  2. 必选条件:固定匹配指定分类(category 参数)

典型场景:如仅查询「电子产品」分类中参与促销的商品。

在这里插入图片描述

执行模板:

GET products/_search/template
{
  "id": "conditional_search_template",
  "params": {
    "is_on_sale": true,
    "category": "电子产品"
  }
}

在这里插入图片描述

为什么原始模板会失败?

  • 语法错误:Mustache 的条件语句 {{#param}} 不能直接作为 JSON 键名使用。
  • 结构问题:Elasticsearch 查询 DSL 必须是有效的 JSON,而原始模板在解析时破坏了 JSON 结构。
  • 模板解析顺序:Mustache 先于 JSON 解析执行,导致语法冲突。

正确方式应包裹整个查询块,而非作为 JSON 键名。

3.3.1 方案 1:使用 JSON 转义

POST _scripts/conditional_search_template_v2
{
  "script": {
    "lang": "mustache",
    "source": {
      "query": {
        "bool": {
          "must": [
            "{{#is_on_sale}}",
            {"term": {"on_sale": true}},
            "{{/is_on_sale}}",
            {"match": {"category": "{{category}}"}}
          ]
        }
      }
    }
  }
}

GET products/_search/template
{
  "id": "conditional_search_template_v2",
  "params": {
    "is_on_sale": true,
    "category": "电子产品"
  }
}

注意

  • 需要 Elasticsearch 7.12+ 版本支持。
  • 可能对复杂模板不友好。

在这里插入图片描述

3.3.2 方案 2:将整个模板作为字符串传递(推荐)

POST _scripts/conditional_search_template_v3
{
  "script": {
    "lang": "mustache",
    "source": """{
      "query": {
        "bool": {
          "must": [
            {{#is_on_sale}}
            {"term": {"on_sale": true}},
            {{/is_on_sale}}
            {"match": {"category": "{{category}}"}}
          ]
        }
      }
    }"""
  }
}

GET products/_search/template
{
  "id": "conditional_search_template_v3",
  "params": {
    "is_on_sale": true,
    "category": "电子产品"
  }
}

关键点

  • 使用 三引号 """ 包裹整个模板内容。
  • 保持模板内的 Mustache 语法不变。
  • 这是 Elasticsearch 官方推荐的方式。

在这里插入图片描述

3.4 案例 3:多索引搜索模板

POST _scripts/multi_index_search_template
{
  "script": {
    "lang": "mustache",
    "source": {
      "query": {
        "multi_match": {
          "query": "{{query}}",
          "fields": ["title^2", "content"]
        }
      },
      "_source": ["title", "created_at"],
      "highlight": {
        "fields": {
          "content": {}
        }
      }
    }
  }
}

这段代码定义了一个名为 multi_index_search_template 的 Elasticsearch 检索模板,核心功能是:

跨索引全文检索,主要特性包括:

  1. 多字段搜索:在 title(权重加倍)和 content 字段中匹配用户输入的关键词(query 参数)。
  2. 结果优化
    • 只返回 titlecreated_at 字段(_source 过滤)。
    • 对匹配内容高亮显示(highlight 聚焦 content 字段)。

典型场景

  • 同时搜索博客(blog)和新闻(news)索引(需在调用时指定索引)。
  • 适用于站内统一搜索引擎,如输入「Elasticsearch」同时显示相关文章标题和摘要片段。

在这里插入图片描述

执行模板:

GET blog,news/_search/template
{
  "id": "multi_index_search_template",
  "params": {
    "query": "Elasticsearch"
  }
}

在这里插入图片描述

3.5 模板管理

删除模板:

DELETE _scripts/template_name

在这里插入图片描述

查看所有模板:

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

在这里插入图片描述

检索模板是 Elasticsearch 中强大的功能,特别适合构建搜索 API 或需要频繁执行类似但参数不同的查询场景。通过模板可以保持查询一致性,同时提供必要的灵活性。

4.{#param}} 和 {{/param}}

在 Mustache 模板语言中,{{#param}}{{/param}} 是一对 条件块标签,用于控制模板内容的渲染逻辑。它们的具体含义如下:

4.1 {{#param}} 的含义

  • 开始条件块:表示一个条件判断的开始
  • 行为取决于参数类型
    • param布尔值 true非空列表 → 渲染块内内容
    • paramfalse / 空列表 / null / undefined → 跳过块内内容
    • param对象 → 进入当前对象的上下文(可以访问对象属性)

4.2 {{/param}} 的含义

  • 结束条件块:表示条件判断的结束。
  • 必须与 {{#param}} 成对出现:就像 HTML 的闭合标签。

4.3 关键注意事项

  • 必须严格闭合:每个 {{#param}} 必须有对应的 {{/param}}
  • JSON 有效性
    • 条件块内的内容需要保持合法的 JSON 结构。
    • 可能需要处理尾随逗号问题。
  • 参数传递
    GET _search/template
    {
      "id": "my_template",
      "params": {
        "on_sale": true,      // 布尔值
        "tags": ["a","b"],    // 数组
        "price_range": {      // 对象
          "min": 100,
          "max": 500
        }
      }
    }
    

4.4 为什么 Elasticsearch 使用这种语法?

  • 逻辑与表现分离:模板只关注 “是否渲染”,不包含复杂逻辑。
  • 安全性:防止代码注入(比拼接字符串更安全)。
  • 跨语言兼容:Mustache 是多种语言支持的模板标准。

这种设计使得模板既灵活又可维护,特别适合作为搜索 API 的抽象层。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

G皮T

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值