20 KiB
20 KiB
数据模型
**本文档引用的文件** - [backend/app/models/__init__.py](file://backend/app/models/__init__.py) - [backend/app/models/user.py](file://backend/app/models/user.py) - [backend/app/models/query.py](file://backend/app/models/query.py) - [backend/app/models/query_task.py](file://backend/app/models/query_task.py) - [backend/app/models/citation_record.py](file://backend/app/models/citation_record.py) - [backend/app/models/subscription.py](file://backend/app/models/subscription.py) - [backend/app/database.py](file://backend/app/database.py) - [backend/alembic/versions/488d0bd5ab01_initial_migration.py](file://backend/alembic/versions/488d0bd5ab01_initial_migration.py) - [backend/app/schemas/query.py](file://backend/app/schemas/query.py) - [backend/app/schemas/citation.py](file://backend/app/schemas/citation.py) - [backend/app/services/query.py](file://backend/app/services/query.py) - [backend/app/api/queries.py](file://backend/app/api/queries.py) - [backend/app/services/citation.py](file://backend/app/services/citation.py) - [backend/app/api/citations.py](file://backend/app/api/citations.py) - [backend/app/config.py](file://backend/app/config.py) - [backend/app/api/deps.py](file://backend/app/api/deps.py)更新摘要
所做更改
- 完善了用户模型的字段映射和关系配置说明
- 详细补充了查询模型的索引策略和生命周期管理
- 新增了查询任务模型的状态机和任务调度机制
- 完善了引用记录模型的统计分析功能说明
- 补充了订阅模型的支付信息字段和状态管理
- 增强了模型间关系映射和级联策略的技术细节
- 完善了序列化、反序列化与数据验证机制
- 新增了使用示例和最佳实践指南
目录
简介
本文件系统性梳理 GEO 平台的 SQLAlchemy ORM 数据模型,覆盖模型类定义、字段映射与关系配置,解释模型间的关系映射(含级联与外键约束)、序列化/反序列化与数据验证机制、生命周期管理与事件钩子、以及使用示例与最佳实践。目标是帮助开发者快速理解并正确使用数据模型,确保在查询、任务调度、引用记录与订阅管理等场景中保持一致性与可维护性。
项目结构
后端采用异步 SQLAlchemy(SQLAlchemy 2.x + asyncpg)与 Pydantic 模式进行数据建模与 API 层交互。数据库初始化通过 declarative_base 创建基类,迁移脚本由 Alembic 管理,模型导出统一在 models 包的 init.py 中聚合。
graph TB
subgraph "模型层"
U["User<br/>用户"]
Q["Query<br/>查询任务"]
QT["QueryTask<br/>查询任务执行单元"]
CR["CitationRecord<br/>引用记录"]
S["Subscription<br/>订阅"]
end
subgraph "数据库"
DB["PostgreSQL"]
end
subgraph "服务层"
SVCQ["Query 服务"]
SVCC["Citation 服务"]
end
subgraph "API 层"
APIQ["Queries API"]
APIC["Citations API"]
end
U --> Q
Q --> CR
Q --> QT
U --> S
SVCQ --> Q
SVCC --> CR
APIQ --> SVCQ
APIC --> SVCC
Q --- DB
CR --- DB
QT --- DB
S --- DB
U --- DB
图表来源
- backend/app/models/user.py:11-41
- backend/app/models/query.py:11-55
- backend/app/models/query_task.py:11-39
- backend/app/models/citation_record.py:11-42
- backend/app/models/subscription.py:11-37
- backend/app/database.py:1-29
- backend/app/services/query.py:1-123
- backend/app/services/citation.py:1-359
- backend/app/api/queries.py:1-86
- backend/app/api/citations.py:1-78
章节来源
核心组件
本节概述各模型的职责、关键字段与关系,为后续深入分析打基础。
- 用户(User)
- 负责平台用户信息与配额控制,支持计划类型与最大查询数限制。
- 关系:一对多到 Query、Subscription,删除时级联删除孤儿对象。
- 查询(Query)
- 描述关键词、目标品牌、别名、平台集合、频率、状态及下次查询时间等。
- 关系:多对一到 User;一对多到 CitationRecord、QueryTask;删除时级联删除孤儿对象。
- 查询任务(QueryTask)
- 记录单次平台查询任务的状态、错误信息与时间戳。
- 关系:多对一到 Query;删除时级联删除。
- 引用记录(CitationRecord)
- 记录某次查询在特定平台上的引用情况、竞品品牌列表与原始响应摘要。
- 关系:多对一到 Query;删除时级联删除。
- 订阅(Subscription)
- 记录用户的订阅计划、有效期、支付信息与状态。
- 关系:多对一到 User;删除时级联删除。
章节来源
- backend/app/models/user.py:11-41
- backend/app/models/query.py:11-55
- backend/app/models/query_task.py:11-39
- backend/app/models/citation_record.py:11-42
- backend/app/models/subscription.py:11-37
架构总览
下图展示模型与数据库表、索引、外键约束之间的对应关系,以及服务层与 API 层如何通过模型进行数据访问。
erDiagram
USERS {
uuid id PK
string email UK
string password_hash
string name
string plan
integer max_queries
boolean is_active
timestamptz created_at
timestamptz updated_at
}
QUERIES {
uuid id PK
uuid user_id FK
string keyword
string target_brand
jsonb brand_aliases
jsonb platforms
string frequency
string status
timestamptz last_queried_at
timestamptz next_query_at
timestamptz created_at
timestamptz 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
timestamptz queried_at
}
QUERY_TASKS {
uuid id PK
uuid query_id FK
string platform
string status
text error_message
timestamptz scheduled_at
timestamptz started_at
timestamptz 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
timestamptz created_at
}
USERS ||--o{ QUERIES : "拥有"
USERS ||--o{ SUBSCRIPTIONS : "拥有"
QUERIES ||--o{ CITATION_RECORDS : "产生"
QUERIES ||--o{ QUERY_TASKS : "拆分执行"
图表来源
- backend/alembic/versions/488d0bd5ab01_initial_migration.py:21-128
- backend/app/models/user.py:11-41
- backend/app/models/query.py:11-55
- backend/app/models/citation_record.py:11-42
- backend/app/models/query_task.py:11-39
- backend/app/models/subscription.py:11-37
详细组件分析
用户模型(User)
- 表名与主键
- 表名:users;主键:UUID 类型的 id。
- 字段映射
- 邮箱唯一且必填;密码哈希必填;名称可空;计划默认 free;最大查询数默认 5;激活状态默认 true;创建/更新时间自动填充。
- 关系
- 一对多到 Query、Subscription,删除用户时级联删除孤儿对象。
- 生命周期与事件
- created_at/updated_at 使用 server_default/onupdate 注入数据库侧时间戳。
- 序列化/反序列化
- 通过 Pydantic 模型(如查询响应)在 API 层进行序列化;ORM 对象可直接用于 FastAPI 响应模型(from_attributes)。
- 最佳实践
- 在创建/更新用户时避免直接修改计划或配额,建议通过专门的服务接口进行校验与审计。
章节来源
查询模型(Query)
- 表名与主键
- 表名:queries;主键:UUID 类型的 id。
- 字段映射
- 外键 user_id 指向 users.id,删除时级联;关键词与目标品牌必填;品牌别名与平台集合默认值合理;频率默认 weekly;状态默认 active;下次查询时间可空;创建/更新时间自动填充。
- 关系
- 多对一到 User;一对多到 CitationRecord、QueryTask,删除查询时级联删除孤儿对象。
- 索引
- 为 user_id、status、next_query_at 建立索引以优化查询。
- 生命周期与事件
- created_at/updated_at 使用 server_default/onupdate 注入数据库侧时间戳。
- 序列化/反序列化
- 响应模型 QueryResponse 支持 from_attributes,便于 ORM 对象直接转为 API 响应。
- 最佳实践
- 更新频率时同步更新 next_query_at;在创建查询前检查用户配额。
章节来源
查询任务模型(QueryTask)
- 表名与主键
- 表名:query_tasks;主键:UUID 类型的 id。
- 字段映射
- 外键 query_id 指向 queries.id,删除时级联;平台必填;状态默认 pending;错误信息可空;调度/开始/完成时间可空。
- 关系
- 多对一到 Query;删除查询任务时级联删除。
- 索引
- 为 status 建立索引以支持任务调度筛选。
- 生命周期与事件
- scheduled_at 默认当前时间;其他时间戳按需更新。
- 序列化/反序列化
- 通过 Pydantic 模型进行 API 层序列化。
- 最佳实践
- 任务状态机:pending -> started -> completed 或 failed;失败时记录 error_message。
章节来源
- backend/app/models/query_task.py:11-39
- backend/alembic/versions/488d0bd5ab01_initial_migration.py:80-94
引用记录模型(CitationRecord)
- 表名与主键
- 表名:citation_records;主键:UUID 类型的 id。
- 字段映射
- 外键 query_id 指向 queries.id,删除时级联;平台必填;是否引用默认 false;引用位置可空;引用文本可空;竞品品牌列表默认空数组;原始响应可空;查询时间默认当前时间。
- 关系
- 多对一到 Query;删除查询时级联删除。
- 索引
- 为 query_id、queried_at、platform 建立索引以优化统计与检索。
- 生命周期与事件
- queried_at 默认当前时间。
- 序列化/反序列化
- 通过 CitationResponse 进行 API 层序列化。
- 最佳实践
- 统计时按平台与日期聚合,结合索引提升性能。
章节来源
- backend/app/models/citation_record.py:11-42
- backend/alembic/versions/488d0bd5ab01_initial_migration.py:61-78
订阅模型(Subscription)
- 表名与主键
- 表名:subscriptions;主键:UUID 类型的 id。
- 字段映射
- 外键 user_id 指向 users.id,删除时级联;计划必填;状态默认 active;起止日期必填;金额可空;支付方式与支付 ID 可空;创建时间默认当前时间。
- 关系
- 多对一到 User;删除用户时级联删除。
- 生命周期与事件
- created_at 默认当前时间。
- 序列化/反序列化
- 通过 Pydantic 模型进行 API 层序列化。
- 最佳实践
- 订阅到期后应自动调整用户配额与功能权限。
章节来源
- backend/app/models/subscription.py:11-37
- backend/alembic/versions/488d0bd5ab01_initial_migration.py:96-111
模型关系与级联策略
- 外键约束
- 所有子表均设置外键指向父表主键,并在删除时采用 CASCADE,确保数据一致性。
- 级联删除孤儿对象
- User 的 queries、subscriptions;Query 的 citation_records、query_tasks 均配置了"all, delete-orphan",保证删除父对象时自动清理其子对象。
- 索引策略
- 查询高频字段(如 user_id、status、next_query_at、queried_at、platform)建立索引,提升查询性能。
章节来源
- backend/app/models/user.py:35-40
- backend/app/models/query.py:43-48
- backend/app/models/query_task.py:36-38
- backend/app/models/citation_record.py:37-41
序列化、反序列化与数据验证
- Pydantic 验证
- 查询创建/更新请求体包含平台集合、频率、状态等字段的严格校验,非法值会抛出异常。
- ORM 到 API 的转换
- 响应模型启用 from_attributes,允许直接将 ORM 对象转为 JSON 响应。
- API 层集成
- Queries API 将请求体绑定到 Pydantic 模型,调用服务层进行业务处理,再返回 ORM 对象或 Pydantic 响应模型。
章节来源
- backend/app/schemas/query.py:11-94
- backend/app/schemas/citation.py:7-50
- backend/app/api/queries.py:1-86
生命周期管理与事件钩子
- 时间戳管理
- 所有模型的 created_at/updated_at 使用 server_default/onupdate 注入数据库侧时间戳,减少应用层负担。
- 任务状态流转
- QueryTask 的状态从 pending 到 started 再到 completed 或 failed,配合 scheduled_at/started_at/completed_at 字段记录生命周期节点。
- 查询调度
- 服务层根据频率计算 next_query_at,便于定时任务调度。
章节来源
- backend/app/models/user.py:25-33
- backend/app/models/query.py:32-40
- backend/app/models/query_task.py:27-32
- backend/app/services/query.py:62-77
使用示例与最佳实践
- 创建查询
- 步骤:校验用户配额 -> 计算 next_query_at -> 构造 Query -> 提交事务 -> 刷新对象。
- 参考路径:创建查询服务:45-81
- 更新查询
- 步骤:读取查询 -> 排除未设置字段 -> 若更新频率则重算 next_query_at -> 提交事务 -> 刷新对象。
- 参考路径:更新查询服务:84-113
- 删除查询
- 步骤:按用户与查询 ID 定位 -> 删除 -> 提交事务。
- 参考路径:删除查询服务:116-129
- API 调用
- GET /queries -> 返回 QueryListResponse
- POST /queries -> 返回 QueryResponse
- GET /queries/{query_id} -> 返回 QueryResponse
- PUT /queries/{query_id} -> 返回 QueryResponse
- DELETE /queries/{query_id} -> 204 No Content
- 参考路径:查询 API:15-86
章节来源
依赖关系分析
- 数据库引擎与会话
- 使用异步引擎与 async_sessionmaker,Base 作为 declarative_base 基类。
- 模型导出
- models/init.py 统一导出所有模型,便于上层模块按需导入。
- 迁移脚本
- Alembic 初始迁移脚本定义了表结构、索引与外键约束,与模型定义保持一致。
graph LR
CFG["配置<br/>DATABASE_URL"] --> ENG["异步引擎"]
ENG --> SESS["AsyncSessionLocal"]
SESS --> BASE["declarative_base"]
BASE --> MODELS["模型类"]
MODELS --> DB["PostgreSQL"]
图表来源
章节来源
性能考量
- 索引设计
- queries:user_id、status、next_query_at
- citation_records:query_id、queried_at、platform
- query_tasks:status
- 建议:基于实际查询模式持续评估与补充索引。
- 查询优化
- 使用 select + order_by + offset + limit 实现分页与排序。
- 使用 func.count 统计总数,避免不必要的全量加载。
- 异步 I/O
- 使用 asyncpg 与 SQLAlchemy 异步引擎,降低并发场景下的阻塞风险。
- 缓存策略
- 对热点查询结果(如用户配额、订阅状态)可引入 Redis 缓存,减少数据库压力。
故障排查指南
- 查询配额超限
- 现象:创建查询时报错"PermissionError: Query limit exceeded"
- 处理:检查用户 max_queries 与当前查询数量,必要时升级计划或清理历史查询。
- 参考路径:创建查询服务:45-81
- 查询不存在
- 现象:GET/PUT/DELETE 查询返回 404
- 处理:确认 query_id 与当前用户匹配;检查软删除/级联删除是否生效。
- 参考路径:查询 API:42-85
- 平台/频率参数非法
- 现象:Pydantic 校验失败
- 处理:核对平台集合是否在允许集合内,频率是否为 daily/weekly。
- 参考路径:查询请求体校验:18-33
- 任务状态异常
- 现象:任务长时间 pending 或失败
- 处理:检查 error_message 字段;核对平台可用性与 API 密钥配置。
- 参考路径:查询任务模型:11-39
章节来源
- backend/app/services/query.py:45-129
- backend/app/api/queries.py:42-85
- backend/app/schemas/query.py:18-33
- backend/app/models/query_task.py:11-39
结论
GEO 项目的数据模型围绕用户、查询、任务、引用记录与订阅五大实体构建,采用异步 SQLAlchemy ORM 与 Alembic 迁移管理,配合 Pydantic 的输入输出验证,形成清晰的领域模型与 API 边界。通过合理的外键约束、级联策略与索引设计,既保证了数据一致性,也兼顾了查询性能。建议在生产环境中持续监控查询性能与缓存命中率,并完善事件钩子与审计日志以增强可观测性。
附录
- 数据库连接配置
- DATABASE_URL:PostgreSQL 异步连接字符串
- 参考路径:配置
- 模型导出入口
- models/init.py 统一导出所有模型
- 参考路径:模型导出:1-14
- JWT 认证配置
- JWT_SECRET:JWT 密钥
- JWT_EXPIRE_HOURS:JWT 过期时间(小时)
- 参考路径:认证依赖:16-43