尧图建网站 尧图建网站 YAOTU WEB BUILD 免费咨询
ARTICLE DETAIL

资讯详情

深耕网站建设与建站编程的一线实战洞察。

JeecgBoot 全文检索实战:从数据库 LIKE 到 Elasticsearch 集成的完整迁移

JeecgBoot 全文检索实战:从数据库 LIKE 到 Elasticsearch 集成的完整迁移 JeecgBoot 全文检索实战从数据库 LIKE 到 Elasticsearch 集成的完整迁移【免费下载链接】jeecg-boot【低代码迈入v2.0时代一句话即可生成整个系统】企业级AI低代码平台一键生成前后端代码甚至整个系统。 AI Skills 一句话画流程、设计表单、生成报表、大屏。内置 AI应用平台涵盖AI聊天、知识库、流程编排、MCP插件等兼容主流大模型。引领AI低代码「Skills 生成 → 在线配置 → 代码生成 → 手工合并-AI修改」开发模式解决 Java 项目 90% 重复工作提高效率又不失灵活。项目地址: https://gitcode.com/GitHub_Trending/je/jeecg-boot如果你的系统里有一张两百万行的用户表前端搜索框每敲一个字就触发一次LIKE %关键字%查询你会发现接口耗时从几十毫秒一路涨到几秒数据库 CPU 也随之报警。这是很多管理后台的真实处境也是我们决定把 JeecgBoot 的搜索能力迁移到 Elasticsearch 的直接原因。这篇文章就围绕 JeecgBoot Elasticsearch 集成的完整过程展开记录我们从零配置、写代码到踩坑排错的全流程读完你可以照着在自己的 JeecgBoot 项目里复现一遍。为什么非换不可先看 LIKE 查询的三个硬伤在动手之前我们先说清楚为什么要迁移否则你会觉得这是没事找事。第一个硬伤是扫描成本。LIKE %关键词%无法利用 B 树索引本质是全表扫描数据量过百万后性能断崖式下跌。第二个硬伤是命中率。用户搜张伟数据库只认字面完全一致的匹配想支持错别字容忍同义词扩展拼音前缀这类体验SQL 基本无能为力。第三个硬伤是排序。相关性打分比如标题命中比正文命中权重更高在数据库里要靠手写复杂 CASE WHEN维护成本极高。Elasticsearch 解决的正是这三件事倒排索引、分词与打分。它不替代数据库做主存储而是作为检索副本存在——数据先落库再同步到 ES。前置条件三条清单一项都不能少JeecgBoot 对 ES 的封装基于 REST API 实现不依赖重量级客户端依赖这一点对新手非常友好。动手前确认三件事Elasticsearch 服务7.x 及以上版本均可8.x 也兼容代码里针对 7.x 做了显式兼容处理。JeecgBoot 工程任意 3.x 版本即可ES 相关类位于jeecg-boot-base-core模块无需额外引入 starter。Java Maven 环境能正常编译运行 JeecgBoot 即可。这里有个值得注意的设计模板类的注册是有条件的。查看源码会发现JeecgElasticsearchTemplate上标了ConditionalOnProperty(prefix jeecg.elasticsearch, name cluster-nodes)意思是只有当你配置了 ES 地址这个 Bean 才会被创建。没配 ES 的项目不会因为类加载而报错这也是它能作为可选功能安静存在的原因。核心配置类源码jeecg-boot/jeecg-boot-base-core/src/main/java/org/jeecg/config/vo/Elasticsearch.java三步完成 ES 连接配置配置集中在application.yml总共就两个键加上注释也不到十行jeecg: elasticsearch: cluster-nodes: 127.0.0.1:9200 # ES 服务地址多个节点用逗号分隔 check-enabled: true # 启动时是否校验连接建议开发期打开这段配置的作用很直白cluster-nodes是模板类拼接请求 URL 的基础地址check-enabled控制项目启动时是否主动探测一次 ES 版本号。check-enabled: true时启动日志里会出现两行关键信息ElasticSearch 服务连接成功和ElasticSearch version: 7.x.x。如果 ES 没起来日志会给出明确的失败警告并且后续所有操作都会被拒——这是官方故意设计的熔断避免你在服务不可用时做无意义的写入。核心实操索引与增删改查ES 相关代码集中在模板类里先注入它配置文件中的映射关系由JeecgBaseConfig统一管理相关源码见jeecg-boot/jeecg-boot-base-core/src/main/java/org/jeecg/config/JeecgBaseConfig.javaResource private JeecgElasticsearchTemplate esTemplate;1. 创建与检查索引// 返回 true 表示索引创建成功若索引已存在会打印警告并返回 false boolean created esTemplate.createIndex(sys_user_index); // 判断索引是否存在常用于启动时的幂等初始化 boolean exists esTemplate.indexExists(sys_user_index);这段代码在做什么createIndex底层发的是PUT /{indexName}靠返回体的acknowledged字段判断成败已存在的索引不会抛异常只会打一条警告方便你重复执行初始化逻辑。2. 写入与更新数据JSONObject user new JSONObject(); user.put(id, u_1001); user.put(username, 张三); user.put(deptName, 研发部); // typeName 只是分类标识不是数据库表名随便起但要统一 esTemplate.saveOrUpdate(sys_user_index, docs, u_1001, user);这段代码在做什么saveOrUpdate发的是PUT /{indexName}/{typeName}/{dataId}?refreshwait_forwait_for表示写入后等待刷新完成再返回保证你立刻能查到刚写入的数据代价是写入吞吐略降适合低频同步场景。3. 按 ID 查询与删除// 查不到时返回 null而不是空对象 JSONObject doc esTemplate.getDataById(sys_user_index, docs, u_1001); // 删除成功返回 true文档不存在返回 false boolean deleted esTemplate.delete(sys_user_index, docs, u_1001);这段代码在做什么这两个方法分别对应GET和DELETE请求且都对 404 做了兜底处理不会因为文档不存在而抛出异常打断你的业务逻辑。4. 批量写入JSONArray list new JSONArray(); // 注意数组里每个元素必须带 id 字段模板会用它作为文档 _id list.add(userJson1); list.add(userJson2); esTemplate.saveBatch(sys_user_index, docs, list);这段代码在做什么saveBatch走的是 ES 的_bulk批量接口把所有数据拼成一条请求发送网络往返从 N 次降到 1 次是全量初始化索引时最该用的方法。查询实操从关键词到组合条件查询是 ES 集成的重头戏模板类给了一套搭积木式的构造方法。全文检索一段代码搞定// 在 username、deptName 两个字段里搜研发 JSONObject query esTemplate.buildQueryString(username OR deptName, 研发); // 组装完整请求只返回指定字段从第 0 条开始取 10 条 JSONObject body esTemplate.buildQuery(null, query, 0, 10); JSONObject result esTemplate.search(sys_user_index, docs, body);这段代码在做什么buildQueryString生成query_string查询 DSL支持AND、OR、NOT及*通配符buildQuery负责把查询条件、分页参数和字段过滤拼成完整请求体。组合查询过滤 范围 关键字JSONArray must new JSONArray(); must.add(esTemplate.buildQueryString(status, 1)); // 状态必须为 1 must.add(esTemplate.buildRangeQuery(createTime, 2024-01-01, 2024-12-31, true, true)); JSONObject query esTemplate.buildBoolQuery(must, null, null); // bool 查询must 条件全中这段代码在做什么buildBoolQuery对应 DSL 里的bool查询三个参数分别是 must必须满足、mustNot必须排除、should满足加分buildRangeQuery生成范围条件gte/lte是否包含边界由最后两个布尔参数控制。如果查询条件更复杂模板还提供了QueryStringBuilder这个链式工具支持.and(...)、.or(...)、.not(...)连续拼接适合在代码里动态组装复杂的检索表达式。避坑指南四个高频问题问题一启动日志提示连接失败但 ES 明明在跑。先确认cluster-nodes里没写http://前缀——模板类会自己拼http://写了反而拼出http://http://。再看 ES 是否绑定了127.0.0.1跨机器访问记得放开监听地址。问题二写入报failed to parse field ... of type [text]。这是模板类里最典型的一个坑。看saveOrUpdate源码会发现它写入前会主动剔除两类字段空值字段以及包含[{前缀的上传控件字段比如富文本、图片路径。原因很简单这类值在 ES 里无法解析成合法的 text。你自己封装写入方法时也要记得过滤这两种字段否则报错会非常隐蔽。问题三一次查询只能拿到 10000 条这是 ES 的分页硬上限模板类里定义了ES_MAX_SIZE 10000。业务上如果需要深分页应该改用 search_after 或 scroll 方案而不是盲目加大 size。问题四getIndexMapping返回 null。模板对 ES 7.x 做了include_type_nametrue的兼容处理但如果你用的是 8.x 且未显式指定 type 名称映射结构可能对不上。遇到这种情况先手动调一次GET /{index}/{type}/_mapping对比返回结构再决定是否需要自定义解析。性能与维护三句可落地的话全量同步用saveBatch增量同步用saveOrUpdate别反过来——逐条写 ES 的性能和批量写入差一个数量级。业务数据变更处加同步钩子比如在 Service 层保存方法成功后调用 ES 更新同时用定时任务兜底对账保证 ES 与数据库最终一致。上线前用getIndices列一次索引清单配合getIndexMappingFormat检查字段类型是否符合预期避免索引建了但字段全是 text 没法做精确过滤这类隐形问题。收尾先跑通最小闭环回到开头的用户表场景——两百万行数据、几秒的 LIKE 查询在我们接入 ES 后变成了几十毫秒的关键词检索命中率也因为分词和通配支持明显提升。但请记住ES 不是银弹它解决的是检索问题事务、强一致、复杂关联查询仍然要交给数据库。下一步行动很明确先在测试环境搭一个最小 ES 实例按上文完成配置、跑通建索引 → 写入 → 查询三步闭环再逐步把真实业务表同步进来。整个过程不需要引入额外依赖改的是配置和几段 Service 代码风险完全可控。【免费下载链接】jeecg-boot【低代码迈入v2.0时代一句话即可生成整个系统】企业级AI低代码平台一键生成前后端代码甚至整个系统。 AI Skills 一句话画流程、设计表单、生成报表、大屏。内置 AI应用平台涵盖AI聊天、知识库、流程编排、MCP插件等兼容主流大模型。引领AI低代码「Skills 生成 → 在线配置 → 代码生成 → 手工合并-AI修改」开发模式解决 Java 项目 90% 重复工作提高效率又不失灵活。项目地址: https://gitcode.com/GitHub_Trending/je/jeecg-boot创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表