**变更概述:** - 将 MVP 架构设计文档独立到项目根目录 `mvp/` - 整理 `docs/` 为纯学习和分析文档目录 - 按类型分类:learning(学习)、analysis(分析)、reports(报告)、guides(指南) **目录结构:** ``` mvp/ # MVP 架构设计(独立) ├── README.md # 数据库设计总览 ├── architecture/ # 架构文档 │ ├── agent-architecture-mvp.md │ ├── implementation-plan.md │ └── ... └── tables/ # 数据表设计 docs/ # 学习和分析文档 ├── learning/ # 学习笔记(00-08 编号) ├── analysis/ # 分析笔记 + 重构计划 ├── reports/ # 临时报告 └── guides/ # 指南文档 ``` **详细变更:** - docs/README.md → mvp/README.md(数据库设计入口) - docs/architecture/ → mvp/architecture/(架构设计) - docs/tables/ → mvp/tables/(数据表设计) - docs/学习笔记-*.md → docs/learning/07-*.md, 08-*.md - docs/项目学习路径.md → docs/learning/00-*.md - docs/功能分析报告.md → docs/analysis/ - docs/修复报告-*.md → docs/reports/ - docs/日志配置*.md → docs/guides/ 或 docs/reports/ - docs/design/ → docs/analysis/(问题分析和重构计划)
333 lines
7.8 KiB
Markdown
333 lines
7.8 KiB
Markdown
# 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<String, Object> 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(标签分类)
|
||
```
|