Browse Source

fix(知识库): 修复文档分块查询和切换状态功能

- 修复 vector_store 表缺少 create_time 列导致分块查询失败
  - 添加幂等迁移方法,自动为 vector_store 表添加 create_time 列
  - 兼容 Spring AI 自动建表时不含此列的情况

- 修复切换文档启用/禁用状态失败
  - 解决 PostgreSQL json/jsonb 类型不匹配问题
  - 使用 metadata::jsonb 显式类型转换
  - 统一 enabled 值写入为字符串类型,与搜索过滤条件一致

- 修复批量启用/禁用文档功能
  - 同步修复 batchToggleDocuments 方法的相同问题

影响范围:
- 文档分块查看/编辑/删除功能恢复正常
- 文档启用/禁用功能恢复正常
- 批量操作功能恢复正常

测试验证:
- 文档分块查询: 通过
- 切换文档状态: 通过
- 批量启用文档: 通过
- 全量回归测试: 无新增问题
dev-mcp
wanghanlin 3 weeks ago
parent
commit
db292ff4d0
  1. 36
      src/main/java/com/wok/supportbot/config/DatabaseInitConfig.java
  2. 10
      src/main/java/com/wok/supportbot/service/DocumentService.java

36
src/main/java/com/wok/supportbot/config/DatabaseInitConfig.java

@ -10,7 +10,11 @@ import org.springframework.stereotype.Component;
/**
* 数据库初始化配置
* 应用启动时检查并创建必要的表
* 应用启动时检查并创建必要的表迁移列同步种子数据
*
* 开发规范任何涉及建表增删改列初始数据的变更
* 必须同时更新本类init 方法 init-database.sql手动备用脚本
* 保持两者一致否则新部署环境会丢失变更
*/
@Component
@Slf4j
@ -181,6 +185,9 @@ public class DatabaseInitConfig {
// P0-001: 混合检索 - vector_store 添加全文检索列
safeInit("初始化 vector_store 全文检索", this::initVectorStoreFullTextSearch);
// 迁移 vector_store.create_time Spring AI 自动建表时不包含此列
safeInit("迁移 vector_store.create_time 列", this::addVectorStoreCreateTimeColumn);
// 为所有表添加注释幂等可重复执行
safeInit("应用数据库表注释", this::applyTableComments);
@ -754,6 +761,33 @@ public class DatabaseInitConfig {
}
}
/**
* vector_store 表添加 create_time
* Spring AI 自动建表时不会创建此列 DocumentService 查询分块列表时需要按 create_time 排序
* 幂等已有列则跳过
*/
private void addVectorStoreCreateTimeColumn() {
try {
// 表不存在时直接跳过等待 Spring AI 创建后再迁移
if (!checkTableExists("vector_store")) {
log.debug("vector_store 表尚未创建,跳过 create_time 列迁移");
return;
}
String checkSql = "SELECT COUNT(*) FROM information_schema.columns WHERE table_name = 'vector_store' AND column_name = 'create_time'";
Integer count = jdbcTemplate.queryForObject(checkSql, Integer.class);
if (count != null && count == 0) {
log.info("添加 vector_store.create_time 列");
jdbcTemplate.execute("ALTER TABLE vector_store ADD COLUMN create_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP NOT NULL");
// 为已有记录回填创建时间使用当前时间作为兜底
jdbcTemplate.execute("UPDATE vector_store SET create_time = CURRENT_TIMESTAMP WHERE create_time IS NULL");
log.info("vector_store.create_time 列添加完成");
}
} catch (Exception e) {
log.error("添加 vector_store.create_time 列失败,请手动执行: ALTER TABLE vector_store ADD COLUMN create_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP NOT NULL", e);
}
}
// ==================== P1-001: 用户认证与多用户管理 ====================
private void createSysUserTable() {

10
src/main/java/com/wok/supportbot/service/DocumentService.java

@ -551,12 +551,14 @@ public class DocumentService {
/**
* 同步更新 vector_store 中指定文档所有分块的 enabled metadata
* 使用 JdbcTemplate 直接 UPDATE JSONB 字段
* 使用 JdbcTemplate 直接 UPDATE JSON 字段
* 注意Spring AI PgVectorStore 自动建表时 metadata json 类型不是 jsonb
* 统一写入字符串类型 "true"/"false" searchDocuments 的过滤条件保持一致
*/
private void syncVectorEnabledMetadata(String documentId, boolean enabled) {
String sql = "UPDATE vector_store SET metadata = jsonb_set(metadata, '{enabled}', ?) " +
"WHERE metadata->>'documentId' = ?";
// 写入 JSONB 布尔值true/false而非字符串 "true"/"false"
// 使用 to_jsonb(?::text) 将字符串转换为 JSONB 字符串值 searchDocuments 过滤条件一致
String sql = "UPDATE vector_store SET metadata = (jsonb_set(metadata::jsonb, '{enabled}', " +
"to_jsonb(?::text)))::json WHERE metadata->>'documentId' = ?";
jdbcTemplate.update(sql, enabled ? "true" : "false", documentId);
}

Loading…
Cancel
Save