# 表结构设计 **本文档引用的文件** - [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) ## 目录 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表
主键: id"] --> |外键: user_id| Queries["Queries表
主键: id"] Queries --> |外键: query_id| CitationRecords["CitationRecords表
主键: id"] Queries --> |外键: query_id| QueryTasks["QueryTasks表
主键: id"] Users --> |外键: user_id| Subscriptions["Subscriptions表
主键: 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平台提供了坚实的基础,能够支持用户查询监控、竞争情报分析和订阅管理等核心业务功能。