# api_document - 文档元数据表 ## 表定位 **文档管理表**:管理接口文档的元信息,不负责文档检索(检索由 Milvus 负责) ## 设计理念 ### 文档管理,不是文档检索 **核心定位**: - MySQL 负责文档元数据管理(状态、版本、去重) - Milvus 负责文档内容存储和检索 - 通过 doc_id 关联两者 **MVP版本原则**: - ✅ 最简字段,满足基本管理需求 - ✅ 文件去重(基于 file_hash) - ✅ 状态追踪(索引进度) - ✅ 硬删除(同步删除 Milvus 数据) - ❌ 暂不支持:软删除、启用开关、版本管理(Phase 2) --- ## 表结构(MVP版) ```sql CREATE TABLE api_document ( -- 主键 id BIGINT PRIMARY KEY AUTO_INCREMENT, doc_id VARCHAR(64) UNIQUE NOT NULL COMMENT '文档唯一ID(UUID),关联Milvus', -- 文档分类 fault_category VARCHAR(32) DEFAULT 'EXTERNAL_API' COMMENT '文档类别', fault_source VARCHAR(128) COMMENT '文档归属(省份/服务名)', api_name VARCHAR(128) COMMENT '接口名称', version VARCHAR(32) DEFAULT 'v1.0' COMMENT '文档版本', -- 文件信息 file_name VARCHAR(256) NOT NULL COMMENT '原始文件名', file_path VARCHAR(512) COMMENT '文件存储路径', file_hash VARCHAR(64) COMMENT '文件MD5 hash(用于去重)', file_size BIGINT COMMENT '文件大小(字节)', -- 索引状态 status VARCHAR(16) DEFAULT 'PENDING' COMMENT '索引状态(PENDING/PROCESSING/INDEXED/FAILED)', chunk_count INT DEFAULT 0 COMMENT '分块数量', error_message TEXT COMMENT '失败原因', -- 时间字段 indexed_at DATETIME COMMENT '索引完成时间', created_at DATETIME DEFAULT CURRENT_TIMESTAMP, updated_at DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, -- 索引 UNIQUE INDEX uk_file_hash (file_hash), INDEX idx_doc_id (doc_id), INDEX idx_fault_source (fault_source), INDEX idx_status (status), INDEX idx_created_at (created_at) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='文档元数据表(MVP版)'; ``` --- ## 字段说明 | 字段 | 类型 | 必填 | 说明 | |------|------|------|------| | doc_id | VARCHAR(64) | 是 | **核心**:文档唯一ID,关联 Milvus | | fault_category | VARCHAR(32) | 否 | 文档类别 | | fault_source | VARCHAR(128) | 否 | 文档归属(省份/服务名)| | api_name | VARCHAR(128) | 否 | 接口名称 | | version | VARCHAR(32) | 否 | 文档版本 | | file_name | VARCHAR(256) | 是 | 原始文件名 | | file_path | VARCHAR(512) | 否 | 文件存储路径 | | file_hash | VARCHAR(64) | 否 | **去重关键**:文件MD5 | | file_size | BIGINT | 否 | 文件大小 | | status | VARCHAR(16) | 是 | **状态追踪**:PENDING/PROCESSING/INDEXED/FAILED | | chunk_count | INT | 否 | 分块数量 | | error_message | TEXT | 否 | 失败原因 | | indexed_at | DATETIME | 否 | 索引完成时间 | --- ## 核心设计决策 ### 1. doc_id:MySQL 与 Milvus 的桥梁 ``` 作用: - MySQL:通过 doc_id 管理文档元数据 - Milvus:每个 chunk 的 metadata 中携带 doc_id 关联关系: api_document (MySQL) doc_id: doc-001 ↓ 1:N Milvus chunks chunk_1: {doc_id: 'doc-001', text: '...', vector: [...]} chunk_2: {doc_id: 'doc-001', text: '...', vector: [...]} 管理操作: - 删除文档: DELETE FROM milvus_collection WHERE metadata["doc_id"] == 'doc-001'; DELETE FROM api_document WHERE doc_id = 'doc-001'; ``` ### 2. file_hash:文件去重 ``` 去重流程: 1. 用户上传文件 ↓ 2. 计算文件 MD5 file_hash = md5(file_content) ↓ 3. 检查是否已存在 SELECT * FROM api_document WHERE file_hash = 'abc123...'; ↓ 4a. 如果存在 → 提示"文档已存在" 4b. 如果不存在 → 继续导入 唯一约束:UNIQUE INDEX uk_file_hash (file_hash) ``` ### 3. status:状态追踪 ``` 状态流转: PENDING (待处理) ↓ PROCESSING (处理中) ↓ 成功 INDEXED (已索引) ↓ 失败 FAILED (失败) 用途: - 批量导入时监控进度 - 失败重试 - 统计索引成功率 ``` ### 4. 硬删除策略(MVP) ``` 删除文档时: 1. 删除 Milvus 中的所有分块 2. 删除 MySQL 元数据 3. 可选:删除原始文件 特点: - 简单直接 - 数据彻底删除 - 不可恢复(需谨慎) Phase 2 可增强: - 软删除(archived_at) - 启用开关(enabled) ``` --- ## 数据流 ### 场景1:导入新文档 ``` 1. 用户上传文件 ↓ 2. 计算 hash ↓ 3. 检查去重(MySQL) ↓ 4. 插入元数据(status=PROCESSING) ↓ 5. 后台处理:解析 → 分块 → 向量化 → 存入 Milvus ↓ 6. 更新状态(status=INDEXED, chunk_count=15) ``` ### 场景2:删除文档 ``` 1. 用户删除文档 ↓ 2. 删除 Milvus 数据(WHERE metadata["doc_id"] == 'xxx') ↓ 3. 删除 MySQL 元数据 ↓ 4. 可选:删除原始文件 ``` ### 场景3:重新索引 ``` 1. 删除旧数据(Milvus + MySQL) ↓ 2. 重新导入(同场景1) ``` --- ## 典型查询 ```sql -- 查看文档列表 SELECT doc_id, file_name, version, status, chunk_count, indexed_at FROM api_document WHERE fault_source = '广东' AND status = 'INDEXED' ORDER BY indexed_at DESC; -- 查询失败的文档 SELECT doc_id, file_name, error_message FROM api_document WHERE status = 'FAILED'; -- 统计各状态文档数量 SELECT status, COUNT(*) as count FROM api_document GROUP BY status; ``` --- ## 与 Milvus 的协作 ### Milvus Collection Schema ```python { "collection_name": "api_doc_collection", "fields": [ {"name": "id", "type": "VARCHAR", "is_primary": true}, {"name": "content", "type": "VARCHAR"}, {"name": "vector", "type": "FLOAT_VECTOR", "dim": 1536}, {"name": "metadata", "type": "JSON"} ] } # metadata 结构 { "doc_id": "doc-001", # 关联 MySQL "_source": "/path/to/file", "_file_name": "xxx.docx", "chunkIndex": 0, "totalChunks": 15 } ``` ### Java 代码示例 ```java // 插入时携带 doc_id Map metadata = new HashMap<>(); metadata.put("doc_id", docId); // 关联 MySQL metadata.put("_source", filePath); metadata.put("chunkIndex", chunkIndex); // 删除文档的所有分块 String expr = String.format("metadata[\"doc_id\"] == \"%s\"", docId); milvusClient.delete(DeleteParam.newBuilder() .withCollectionName(COLLECTION_NAME) .withExpr(expr) .build()); ``` --- ## 数据示例 ```sql -- 外部接口文档 INSERT INTO api_document VALUES (1, 'doc-001', 'EXTERNAL_API', '广东', '社保查询', 'v2.1', '广东社保查询v2.1.docx', '/docs/guangdong/social-v2.1.docx', 'abc123...', 1048576, 'INDEXED', 15, NULL, '2024-06-15 10:30:00', NOW(), NOW()); -- 内部服务文档 INSERT INTO api_document VALUES (2, 'doc-002', 'INTERNAL_ERROR', 'order-service', '订单服务API', 'v1.0', '订单服务API文档.pdf', '/docs/internal/order-service-api.pdf', 'def456...', 2097152, 'INDEXED', 20, NULL, '2024-06-14 15:20:00', NOW(), NOW()); -- 处理失败的文档 INSERT INTO api_document VALUES (3, 'doc-003', 'EXTERNAL_API', '江苏', '公积金查询', 'v1.5', '江苏公积金查询.html', '/docs/jiangsu/fund-v1.5.html', 'ghi789...', 512000, 'FAILED', 0, '不支持HTML格式', NULL, NOW(), NOW()); ``` --- ## 数据量预估 ``` 预估:100-200 条 - 外部接口文档:50-100 条 - 内部服务文档:20-50 条 - 其他文档:30-50 条 存储: - 单条记录:约 1KB - 200 条:约 200KB 结论:数据量很小 ``` --- ## MVP 版本的简化 ``` Phase 1(当前): ✅ 基础字段和表结构 ✅ 文件去重(file_hash) ✅ 状态追踪(status) ✅ 硬删除 ✅ 通过 doc_id 关联 Milvus Phase 2(未来增强): ❌ enabled(启用开关) ❌ archived_at(软删除) ❌ batch_id(批次管理) ❌ status 细化 ❌ tags(标签分类) ```