Elasticsearch实战:Java中使用Search Template搜索模板完整教程(流程图+代码可直接运行)
- 一、前言
- 二、核心基础:Java 使用 Search Template 核心概念
- 1. 定义:Java 中使用 Search Template
- 2. 核心依赖
- 3. 核心价值
- 三、Java 使用 Search Template 完整流程图
- 四、环境准备
- 五、第一步:Maven 依赖引入(核心)
- 六、第二步:初始化 RestHighLevelClient 客户端
- 七、第三步:提前在 Kibana 存储搜索模板
- 八、第四步:Java 实现 Search Template 4 种核心用法(生产代码)
- 用法1:Java 执行服务端存储的搜索模板(最常用)
- 用法2:Java 预览搜索模板(调试专用)
- 用法3:Java 内嵌模板(不存储在ES,直接写在Java中)
- 用法4:Java 删除服务端模板
- 九、第五步:Java 解析 Search Template 返回结果
- 十、Java 使用 Search Template 完整调用示例
- 十一、生产环境最佳实践
- 十二、常见问题与解决方案
- 1. 问题:Java 提示模板不存在
- 2. 问题:参数传递不生效
- 3. 问题:版本冲突报错
- 4. 问题:查询无数据
- 十三、总结
- 总结
🌺The Begin🌺点点关注,收藏不迷路🌺 |
一、前言
在上一篇文章中,我们讲解了 Elasticsearch Search Template(搜索模板)的核心概念与DSL用法。在实际企业开发中,90%的场景都是使用 Java 客户端调用搜索模板,实现查询逻辑与业务代码解耦。
本文专门聚焦Java 语言如何使用 Search Template,包含完整流程图、依赖引入、模板存储、4种Java实战用法(执行/预览/内嵌/删除)、生产级代码封装、常见问题,从零到一实现 Java 对接 ES 搜索模板,代码可直接复制到项目中运行。
二、核心基础:Java 使用 Search Template 核心概念
1. 定义:Java 中使用 Search Template
通过Elasticsearch RestHighLevelClient高级客户端,调用服务端存储的搜索模板,仅传递动态参数,由 ES 完成 DSL 拼接与查询执行,实现 Java 代码无硬编码 DSL。
2. 核心依赖
必须使用elasticsearch-rest-high-level-client(7.x/8.x通用)
3. 核心价值
- Java 代码无任何DSL字符串,整洁易维护
- 修改查询逻辑无需修改Java代码、无需发版
- 统一查询规范,多系统复用模板
- 支持动态参数、默认值、条件判断
三、Java 使用 Search Template 完整流程图
四、环境准备
- SpringBoot 2.x/3.x
- Elasticsearch 7.17(通用7.x版本)
- RestHighLevelClient 客户端
- 已创建索引:
product(商品索引) - 已存储模板:
product_search_template
五、第一步:Maven 依赖引入(核心)
在pom.xml中引入 ES 高级客户端依赖:
<!-- Elasticsearch Rest 高级客户端 --><dependency><groupId>org.elasticsearch.client</groupId><artifactId>elasticsearch-rest-high-level-client</artifactId><version>7.17.0</version></dependency><!-- ES 核心包 --><dependency><groupId>org.elasticsearch</groupId><artifactId>elasticsearch</artifactId><version>7.17.0</version></dependency>六、第二步:初始化 RestHighLevelClient 客户端
创建 ES 连接配置类,注入 Bean:
importorg.elasticsearch.client.RestClient;importorg.elasticsearch.client.RestHighLevelClient;importorg.springframework.context.annotation.Bean;importorg.springframework.context.annotation.Configuration;@ConfigurationpublicclassEsConfig{@BeanpublicRestHighLevelClientrestHighLevelClient(){returnnewRestHighLevelClient(RestClient.builder(// ES 地址,多个用逗号分隔newHttpHost("127.0.0.1",9200,"http")));}}七、第三步:提前在 Kibana 存储搜索模板
执行 DSL,创建 Java 要调用的模板:
PUT/_scripts/product_search_template{"script":{"lang":"mustache","source":{"from":"{{from}}{{^from}}0{{/from}}","size":"{{size}}{{^size}}10{{/size}}","query":{"bool":{"must":[{"match":{"name":"{{keyword}}"}}],"filter":[{"term":{"category":"{{category}}"}}]}},"sort":[{"price":"asc"}]}}}八、第四步:Java 实现 Search Template 4 种核心用法(生产代码)
用法1:Java 执行服务端存储的搜索模板(最常用)
直接调用 ES 中已存储的模板,传递参数执行查询,企业生产首选。
importorg.elasticsearch.action.search.SearchResponse;importorg.elasticsearch.client.RequestOptions;importorg.elasticsearch.client.RestHighLevelClient;importorg.elasticsearch.script.ScriptType;importorg.elasticsearch.script.mustache.SearchTemplateRequest;importorg.elasticsearch.script.mustache.SearchTemplateResponse;importorg.springframework.stereotype.Service;importjavax.annotation.Resource;importjava.util.HashMap;importjava.util.Map;@ServicepublicclassEsSearchTemplateService{// 注入ES客户端@ResourceprivateRestHighLevelClientclient;/** * 1. Java 执行服务端存储的 Search Template(生产最常用) * @param keyword 搜索关键词 * @param category 商品分类 * @param pageNum 页码 * @param pageSize 每页条数 * @return 搜索结果 */publicSearchResponsesearchTemplate(Stringkeyword,Stringcategory,intpageNum,intpageSize)throwsException{// 1. 构建搜索模板请求SearchTemplateRequestrequest=newSearchTemplateRequest();// 指定要查询的索引request.setRequest(neworg.elasticsearch.action.search.SearchRequest("product"));// 2. 核心配置:使用服务端存储的模板request.setScriptType(ScriptType.STORED);// 存储型模板request.setScript("product_search_template");// 模板ID// 3. 封装动态参数Map<String,Object>params=newHashMap<>();params.put("from",(pageNum-1)*pageSize);params.put("size",pageSize);params.put("keyword",keyword);params.put("category",category);request.setParams(params);// 4. 执行模板查询SearchTemplateResponseresponse=client.searchTemplate(request,RequestOptions.DEFAULT);// 5. 返回查询结果returnresponse.getResponse();}}用法2:Java 预览搜索模板(调试专用)
不执行查询,只返回拼接后的最终DSL,用于开发调试。
/** * 2. Java 预览搜索模板(调试:查看最终DSL) */publicStringrenderTemplate(Stringkeyword,Stringcategory)throwsException{SearchTemplateRequestrequest=newSearchTemplateRequest();request.setRequest(neworg.elasticsearch.action.search.SearchRequest("product"));// 模板配置request.setScriptType(ScriptType.STORED);request.setScript("product_search_template");// 参数Map<String,Object>params=newHashMap<>();params.put("from",0);params.put("size",10);params.put("keyword",keyword);params.put("category",category);request.setParams(params);// 开启预览模式(不执行查询)request.setSimulate(true);// 执行预览SearchTemplateResponseresponse=client.searchTemplate(request,RequestOptions.DEFAULT);returnresponse.getSource().toString();}用法3:Java 内嵌模板(不存储在ES,直接写在Java中)
模板不存储在ES,直接在Java代码中定义,适合临时简单查询。
/** * 3. Java 内嵌 Search Template(不存ES,直接写代码里) */publicSearchResponseinlineTemplate(Stringkeyword)throwsException{SearchTemplateRequestrequest=newSearchTemplateRequest();request.setRequest(neworg.elasticsearch.action.search.SearchRequest("product"));// 内嵌模板request.setScriptType(ScriptType.INLINE);request.setScript("{\n"+" \"query\": { \"match\": { \"name\": \"{{keyword}}\" } }\n"+"}");// 参数Map<String,Object>params=newHashMap<>();params.put("keyword",keyword);request.setParams(params);// 执行SearchTemplateResponseresponse=client.searchTemplate(request,RequestOptions.DEFAULT);returnresponse.getResponse();}用法4:Java 删除服务端模板
通过 Java 代码删除 ES 中存储的模板。
/** * 4. Java 删除搜索模板 * @param templateId 模板ID */publicvoiddeleteTemplate(StringtemplateId)throwsException{DeleteStoredScriptRequestrequest=newDeleteStoredScriptRequest(templateId);client.deleteScript(request,RequestOptions.DEFAULT);}九、第五步:Java 解析 Search Template 返回结果
执行模板后,解析查询到的文档数据:
/** * 解析模板查询结果 */publicList<Map<String,Object>>parseResponse(SearchResponseresponse){List<Map<String,Object>>resultList=newArrayList<>();SearchHitshits=response.getHits();for(SearchHithit:hits){// 文档数据Map<String,Object>source=hit.getSourceAsMap();// 文档IDStringid=hit.getId();source.put("id",id);resultList.add(source);}returnresultList;}十、Java 使用 Search Template 完整调用示例
// 调用:查询 图书分类、关键词实战、第1页、每页2条SearchResponseresponse=esSearchTemplateService.searchTemplate("实战","图书",1,2);// 解析结果List<Map<String,Object>>result=esSearchTemplateService.parseResponse(response);十一、生产环境最佳实践
优先使用服务端存储模板(ScriptType.STORED)
- 查询逻辑存在ES,Java 无硬编码
- 修改查询无需重启Java服务
统一模板ID命名规范
- 格式:
业务_模块_功能(product_search_template)
- 格式:
调试必须用预览(simulate=true)
- 上线前校验最终DSL是否正确
参数非空校验
- 防止模板渲染报错
模板必须设置默认值
from/size默认值,避免参数为空
十二、常见问题与解决方案
1. 问题:Java 提示模板不存在
✅ 解决方案:检查模板ID是否一致,确认模板已存储到ES
2. 问题:参数传递不生效
✅ 解决方案:检查参数名与模板{{}}变量名完全一致
3. 问题:版本冲突报错
✅ 解决方案:保证 ES 服务端版本与 Java 客户端版本一致
4. 问题:查询无数据
✅ 解决方案:使用预览功能查看最终DSL是否正确
十三、总结
Java 中使用 Elasticsearch Search Template 非常简单,核心就是 3 步:
- 模板提前存储在 ES
- Java 构建参数,通过
SearchTemplateRequest调用 - 执行并解析返回结果
核心API:
SearchTemplateRequest:搜索模板请求ScriptType.STORED:服务端存储模板setParams():传递动态参数client.searchTemplate():执行模板查询
本文提供的代码可直接复制到 SpringBoot 项目中运行,完美实现 Java 对接 Search Template,解决查询硬编码、难以维护的企业级痛点。
总结
- Java 使用 Search Template 核心依赖:RestHighLevelClient
- 生产优先使用:服务端存储模板 + Java传参
- 核心API:
SearchTemplateRequest+ScriptType.STORED - 优势:无硬编码、热更新、易维护、多端复用
🌺The End🌺点点关注,收藏不迷路🌺 |