geo/.qoder/repowiki/zh/content/数据库设计/表结构设计.md

501 lines
17 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 表结构设计
<cite>
**本文档引用的文件**
- [user.py](file://backend/app/models/user.py)
- [query.py](file://backend/app/models/query.py)
- [citation_record.py](file://backend/app/models/citation_record.py)
- [query_task.py](file://backend/app/models/query_task.py)
- [subscription.py](file://backend/app/models/subscription.py)
- [initial_migration.py](file://backend/alembic/versions/488d0bd5ab01_initial_migration.py)
- [database.py](file://backend/app/database.py)
- [config.py](file://backend/app/config.py)
</cite>
## 目录
1. [简介](#简介)
2. [项目结构](#项目结构)
3. [核心组件](#核心组件)
4. [架构概览](#架构概览)
5. [详细组件分析](#详细组件分析)
6. [依赖分析](#依赖分析)
7. [性能考虑](#性能考虑)
8. [故障排除指南](#故障排除指南)
9. [结论](#结论)
## 简介
本文件详细描述GEO项目的数据库表结构设计涵盖用户查询监控平台的核心数据模型。该系统采用PostgreSQL作为主要数据库使用SQLAlchemy ORM进行对象关系映射支持异步数据库操作。系统包含五个核心表users用户表、queries查询表、citation_records引用记录表、query_tasks查询任务表和subscriptions订阅表这些表通过外键关系相互关联形成完整的业务数据模型。
## 项目结构
GEO项目的数据库层采用分层架构设计主要包含以下组件
```mermaid
graph TB
subgraph "数据库层"
DB[(PostgreSQL数据库)]
Engine[异步引擎]
Session[会话管理]
end
subgraph "ORM模型层"
User[User模型]
Query[Query模型]
Citation[CitationRecord模型]
Task[QueryTask模型]
Subscription[Subscription模型]
end
subgraph "配置层"
Config[配置管理]
Alembic[迁移管理]
end
Config --> Engine
Engine --> DB
Session --> DB
User --> DB
Query --> DB
Citation --> DB
Task --> DB
Subscription --> DB
Alembic --> DB
```
**图表来源**
- [database.py:1-29](file://backend/app/database.py#L1-L29)
- [config.py:4-17](file://backend/app/config.py#L4-L17)
**章节来源**
- [database.py:1-29](file://backend/app/database.py#L1-L29)
- [config.py:4-17](file://backend/app/config.py#L4-L17)
## 核心组件
### 数据库连接配置
系统使用异步PostgreSQL连接配置参数如下
- 数据库URL: `postgresql+asyncpg://postgres:postgres123@db:5432/geo_platform`
- Redis连接: `redis://redis:6379/0`
- JWT密钥: `your-secret-key-change-in-production`
- Playwright浏览器路径: `/ms-playwright`
### 异步数据库引擎
使用SQLAlchemy异步引擎创建数据库连接池支持
- 异步会话管理
- 连接池配置
- 自动事务处理
- 连接生命周期管理
**章节来源**
- [config.py:7](file://backend/app/config.py#L7)
- [database.py:6-18](file://backend/app/database.py#L6-L18)
## 架构概览
GEO系统的数据库架构采用标准的三层设计模式
```mermaid
erDiagram
USERS {
uuid id PK
string email UK
string password_hash
string name
string plan
integer max_queries
boolean is_active
timestamp created_at
timestamp updated_at
}
QUERIES {
uuid id PK
uuid user_id FK
string keyword
string target_brand
jsonb brand_aliases
jsonb platforms
string frequency
string status
timestamp last_queried_at
timestamp next_query_at
timestamp created_at
timestamp updated_at
}
CITATION_RECORDS {
uuid id PK
uuid query_id FK
string platform
boolean cited
integer citation_position
text citation_text
jsonb competitor_brands
text raw_response
timestamp queried_at
}
QUERY_TASKS {
uuid id PK
uuid query_id FK
string platform
string status
text error_message
timestamp scheduled_at
timestamp started_at
timestamp completed_at
}
SUBSCRIPTIONS {
uuid id PK
uuid user_id FK
string plan
string status
date start_date
date end_date
numeric amount
string payment_method
string payment_id
timestamp created_at
}
USERS ||--o{ QUERIES : "拥有"
QUERIES ||--o{ CITATION_RECORDS : "包含"
QUERIES ||--o{ QUERY_TASKS : "包含"
USERS ||--o{ SUBSCRIPTIONS : "拥有"
```
**图表来源**
- [initial_migration.py:24-37](file://backend/alembic/versions/488d0bd5ab01_initial_migration.py#L24-L37)
- [initial_migration.py:40-56](file://backend/alembic/versions/488d0bd5ab01_initial_migration.py#L40-L56)
- [initial_migration.py:62-78](file://backend/alembic/versions/488d0bd5ab01_initial_migration.py#L62-L78)
- [initial_migration.py:81-94](file://backend/alembic/versions/488d0bd5ab01_initial_migration.py#L81-L94)
- [initial_migration.py:97-111](file://backend/alembic/versions/488d0bd5ab01_initial_migration.py#L97-L111)
## 详细组件分析
### 用户表 (users)
用户表是整个系统的核心实体,存储平台用户的基本信息和账户状态。
#### 字段定义
| 字段名 | 数据类型 | 约束条件 | 描述 |
|--------|----------|----------|------|
| id | UUID | 主键, 非空, 默认值 | 用户唯一标识符 |
| email | String(255) | 唯一, 非空 | 用户邮箱地址 |
| password_hash | String(255) | 非空 | 用户密码哈希值 |
| name | String(100) | 可空 | 用户姓名 |
| plan | String(20) | 非空, 默认值: "free" | 用户套餐类型 |
| max_queries | Integer | 非空, 默认值: 5 | 最大查询次数限制 |
| is_active | Boolean | 非空, 默认值: true | 账户激活状态 |
| created_at | Timestamp | 非空, 默认值: NOW() | 创建时间 |
| updated_at | Timestamp | 非空, 默认值: NOW() | 更新时间 |
#### 约束和索引
- 主键: id (UUID)
- 唯一约束: email
- 外键: 无直接外键关系
- 关系: 与查询表(一对多)、订阅表(一对多)
#### 业务规则
- 用户必须提供唯一的邮箱地址
- 默认免费套餐最大查询次数为5次
- 账户默认激活状态
- 时间戳自动管理
**章节来源**
- [user.py:14-33](file://backend/app/models/user.py#L14-L33)
- [initial_migration.py:24-37](file://backend/alembic/versions/488d0bd5ab01_initial_migration.py#L24-L37)
### 查询表 (queries)
查询表记录用户的搜索关键词和品牌监控配置。
#### 字段定义
| 字段名 | 数据类型 | 约束条件 | 描述 |
|--------|----------|----------|------|
| id | UUID | 主键, 非空, 默认值 | 查询记录唯一标识符 |
| user_id | UUID | 外键, 非空 | 关联用户ID |
| keyword | String(200) | 非空 | 搜索关键词 |
| target_brand | String(100) | 非空 | 目标品牌名称 |
| brand_aliases | JSONB | 非空, 默认值: [] | 品牌别名列表 |
| platforms | JSONB | 非空, 默认值: ["wenxin","kimi"] | 监控平台列表 |
| frequency | String(20) | 非空, 默认值: "weekly" | 查询频率 |
| status | String(20) | 非空, 默认值: "active" | 查询状态 |
| last_queried_at | Timestamp | 可空 | 最后查询时间 |
| next_query_at | Timestamp | 可空 | 下次查询时间 |
| created_at | Timestamp | 非空, 默认值: NOW() | 创建时间 |
| updated_at | Timestamp | 非空, 默认值: NOW() | 更新时间 |
#### 约束和索引
- 主键: id (UUID)
- 外键: user_id → users.id (级联删除)
- 索引: idx_queries_user_id, idx_queries_status, idx_queries_next_query_at
- 关系: 与用户表(多对一)、引用记录表(一对多)、查询任务表(一对多)
#### 业务规则
- 必须关联有效用户
- 平台默认监控"wenxin"和"kimi"
- 状态默认为"active"
- 支持定时查询调度
- 级联删除确保数据一致性
**章节来源**
- [query.py:14-48](file://backend/app/models/query.py#L14-L48)
- [initial_migration.py:40-56](file://backend/alembic/versions/488d0bd5ab01_initial_migration.py#L40-L56)
### 引用记录表 (citation_records)
引用记录表存储每次查询的具体结果和竞争情报。
#### 字段定义
| 字段名 | 数据类型 | 约束条件 | 描述 |
|--------|----------|----------|------|
| id | UUID | 主键, 非空, 默认值 | 引用记录唯一标识符 |
| query_id | UUID | 外键, 非空 | 关联查询ID |
| platform | String(50) | 非空 | 查询平台名称 |
| cited | Boolean | 非空, 默认值: false | 是否被引用 |
| citation_position | Integer | 可空 | 引用位置 |
| citation_text | Text | 可空 | 引用文本内容 |
| competitor_brands | JSONB | 非空, 默认值: [] | 竞争品牌列表 |
| raw_response | Text | 可空 | 原始响应内容 |
| queried_at | Timestamp | 非空, 默认值: NOW() | 查询时间 |
#### 约束和索引
- 主键: id (UUID)
- 外键: query_id → queries.id (级联删除)
- 索引: idx_citation_records_query_id, idx_citation_records_queried_at, idx_citation_records_platform
- 关系: 与查询表(多对一)
#### 业务规则
- 必须关联有效查询
- 引用状态默认未引用
- 支持JSON格式的竞争品牌数据
- 按平台和查询时间建立索引优化查询性能
- 级联删除确保查询历史完整清理
**章节来源**
- [citation_record.py:14-35](file://backend/app/models/citation_record.py#L14-L35)
- [initial_migration.py:62-78](file://backend/alembic/versions/488d0bd5ab01_initial_migration.py#L62-L78)
### 查询任务表 (query_tasks)
查询任务表管理异步查询任务的状态和执行信息。
#### 字段定义
| 字段名 | 数据类型 | 约束条件 | 描述 |
|--------|----------|----------|------|
| id | UUID | 主键, 非空, 默认值 | 任务唯一标识符 |
| query_id | UUID | 外键, 非空 | 关联查询ID |
| platform | String(50) | 非空 | 执行平台 |
| status | String(20) | 非空, 默认值: "pending" | 任务状态 |
| error_message | Text | 可空 | 错误信息 |
| scheduled_at | Timestamp | 非空, 默认值: NOW() | 调度时间 |
| started_at | Timestamp | 可空 | 开始执行时间 |
| completed_at | Timestamp | 可空 | 完成时间 |
#### 约束和索引
- 主键: id (UUID)
- 外键: query_id → queries.id (级联删除)
- 索引: idx_query_tasks_status
- 关系: 与查询表(多对一)
#### 业务规则
- 必须关联有效查询
- 任务状态默认为"pending"
- 支持任务执行跟踪
- 状态变更自动记录时间戳
- 级联删除确保任务历史清理
**章节来源**
- [query_task.py:14-34](file://backend/app/models/query_task.py#L14-L34)
- [initial_migration.py:81-94](file://backend/alembic/versions/488d0bd5ab01_initial_migration.py#L81-L94)
### 订阅表 (subscriptions)
订阅表管理用户的付费订阅信息和状态。
#### 字段定义
| 字段名 | 数据类型 | 约束条件 | 描述 |
|--------|----------|----------|------|
| id | UUID | 主键, 非空, 默认值 | 订阅记录唯一标识符 |
| user_id | UUID | 外键, 非空 | 关联用户ID |
| plan | String(20) | 非空 | 套餐类型 |
| status | String(20) | 非空, 默认值: "active" | 订阅状态 |
| start_date | Date | 非空 | 订阅开始日期 |
| end_date | Date | 非空 | 订阅结束日期 |
| amount | Numeric(10,2) | 可空 | 支付金额 |
| payment_method | String(50) | 可空 | 支付方式 |
| payment_id | String(255) | 可空 | 支付ID |
| created_at | Timestamp | 非空, 默认值: NOW() | 创建时间 |
#### 约束和索引
- 主键: id (UUID)
- 外键: user_id → users.id (级联删除)
- 关系: 与用户表(多对一)
#### 业务规则
- 必须关联有效用户
- 状态默认为"active"
- 支持多种支付方式
- 日期范围确保订阅有效性
- 级联删除确保订阅历史清理
**章节来源**
- [subscription.py:14-36](file://backend/app/models/subscription.py#L14-L36)
- [initial_migration.py:97-111](file://backend/alembic/versions/488d0bd5ab01_initial_migration.py#L97-L111)
## 依赖分析
### 外键关系图
```mermaid
graph LR
Users["Users表<br/>主键: id"] --> |外键: user_id| Queries["Queries表<br/>主键: id"]
Queries --> |外键: query_id| CitationRecords["CitationRecords表<br/>主键: id"]
Queries --> |外键: query_id| QueryTasks["QueryTasks表<br/>主键: id"]
Users --> |外键: user_id| Subscriptions["Subscriptions表<br/>主键: id"]
style Users fill:#e1f5fe
style Queries fill:#f3e5f5
style CitationRecords fill:#e8f5e8
style QueryTasks fill:#fff3e0
style Subscriptions fill:#fce4ec
```
**图表来源**
- [initial_migration.py:55](file://backend/alembic/versions/488d0bd5ab01_initial_migration.py#L55)
- [initial_migration.py:74](file://backend/alembic/versions/488d0bd5ab01_initial_migration.py#L74)
- [initial_migration.py:92](file://backend/alembic/versions/488d0bd5ab01_initial_migration.py#L92)
- [initial_migration.py:110](file://backend/alembic/versions/488d0bd5ab01_initial_migration.py#L110)
### 关系类型分析
#### 一对一关系
- users ↔ subscriptions: 一个用户对应一个当前有效的订阅记录
#### 一对多关系
- users → queries: 一个用户可以有多个查询记录
- users → subscriptions: 一个用户可以有多个订阅记录
- queries → citation_records: 一个查询可以有多个引用记录
- queries → query_tasks: 一个查询可以有多个任务
#### 多对多关系
- 通过中间表实现的多对多关系不存在于当前设计中
### 级联删除策略
所有外键关系都设置了级联删除策略:
- 删除用户时,自动删除其所有查询、订阅记录
- 删除查询时,自动删除其所有引用记录和任务
**章节来源**
- [initial_migration.py:55](file://backend/alembic/versions/488d0bd5ab01_initial_migration.py#L55)
- [initial_migration.py:74](file://backend/alembic/versions/488d0bd5ab01_initial_migration.py#L74)
- [initial_migration.py:92](file://backend/alembic/versions/488d0bd5ab01_initial_migration.py#L92)
- [initial_migration.py:110](file://backend/alembic/versions/488d0bd5ab01_initial_migration.py#L110)
## 性能考虑
### 索引策略
系统为关键查询字段建立了专门的索引:
#### 查询表索引
- idx_queries_user_id: 提升按用户查询的性能
- idx_queries_status: 支持状态过滤查询
- idx_queries_next_query_at: 优化定时任务调度
#### 引用记录表索引
- idx_citation_records_query_id: 提升按查询获取记录的性能
- idx_citation_records_queried_at: 支持时间序列查询
- idx_citation_records_platform: 优化平台过滤
#### 查询任务表索引
- idx_query_tasks_status: 支持任务状态统计和调度
### 数据类型优化
- 使用UUID作为主键避免序列号暴露业务信息
- JSONB类型存储动态配置支持高效查询和更新
- 数值类型使用Numeric精确存储金额数据
- 时间戳使用带时区的DateTime确保时区一致性
### 查询优化建议
1. **批量操作**: 对于大量数据的插入和更新,使用批量操作减少数据库往返
2. **分页查询**: 对于列表查询,实现分页机制避免一次性加载过多数据
3. **缓存策略**: 结合Redis实现热点数据缓存
4. **连接池管理**: 合理配置连接池大小以平衡性能和资源使用
## 故障排除指南
### 常见问题及解决方案
#### 数据库连接问题
- **症状**: 应用启动时报数据库连接错误
- **原因**: DATABASE_URL配置不正确或数据库服务未启动
- **解决**: 检查.env文件中的DATABASE_URL配置确认数据库服务正常运行
#### 外键约束冲突
- **症状**: 删除用户时报外键约束错误
- **原因**: 存在相关记录导致级联删除失败
- **解决**: 确保级联删除策略正确配置,检查数据完整性
#### 索引性能问题
- **症状**: 查询响应缓慢
- **原因**: 缺少必要的索引或索引设计不当
- **解决**: 分析查询计划,添加适当的索引
#### 数据类型转换错误
- **症状**: JSONB字段操作报错
- **原因**: 数据类型不匹配或格式错误
- **解决**: 确保JSONB数据格式正确使用适当的序列化方法
### 调试工具
1. **数据库监控**: 使用PostgreSQL内置监控工具查看查询性能
2. **日志分析**: 启用SQLAlchemy日志输出分析查询执行情况
3. **性能分析**: 使用EXPLAIN ANALYZE分析慢查询
**章节来源**
- [config.py:7](file://backend/app/config.py#L7)
- [initial_migration.py:114-127](file://backend/alembic/versions/488d0bd5ab01_initial_migration.py#L114-L127)
## 结论
GEO项目的数据库表结构设计体现了现代Web应用的最佳实践
### 设计优势
1. **清晰的数据模型**: 五个核心表覆盖了完整的业务场景
2. **合理的外键关系**: 确保数据一致性和完整性
3. **高效的索引策略**: 针对常见查询模式优化性能
4. **异步数据库支持**: 提供良好的并发处理能力
5. **灵活的数据类型**: JSONB支持动态配置需求
### 业务逻辑实现
- 用户权限控制通过用户表的激活状态实现
- 查询配额控制通过用户表的max_queries字段实现
- 订阅管理通过订阅表的日期范围和状态字段实现
- 数据清理通过级联删除策略自动维护
### 扩展性考虑
系统设计具有良好的扩展性:
- 新增表时可复用现有的UUID主键模式
- JSONB字段支持未来功能的动态配置
- 异步架构支持水平扩展
- 清晰的关系设计便于添加新的业务实体
这个数据模型为GEO平台提供了坚实的基础能够支持用户查询监控、竞争情报分析和订阅管理等核心业务功能。