You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 

5.8 KiB

剧本数据库迁移完成总结

完成日期:2026-02-03
任务类型:数据库迁移补充


任务背景

根据 screenplay-file-parser-service.md 文档中定义的剧本文件解析服务需求,补充创建完整的数据库表结构。

已完成工作

1. 创建数据库迁移文件

文件server/alembic/versions/20260203_1200_create_screenplays_tables.py

内容

  • 创建 screenplays 表(剧本主表)
  • 创建 screenplay_tags 表(剧本元素标签表)
  • 完整的索引策略(包括全文搜索)
  • 数据完整性约束
  • 自动更新触发器
  • 完整的表/列注释

2. 创建 Changelog 文档

文件docs/architecture/changelogs/2026-02-03-screenplays-tables-creation.md

内容

  • 完整的表结构说明
  • 设计原则说明
  • 使用示例代码
  • 后续工作清单
  • 测试建议

3. 更新服务文档

文件docs/requirements/backend/04-services/project/screenplay-file-parser-service.md

变更

  • 移除"数据库字段扩展"章节
  • 添加"数据库表结构"章节
  • 引用迁移文件和 Changelog

技术规范符合性

完全符合 jointo-tech-stack 规范

  1. UUID v7:所有主键使用 UUID v7(应用层生成)
  2. TIMESTAMPTZ:所有时间字段使用 TIMESTAMP(timezone=True)
  3. SMALLINT 枚举:类型字段使用 SMALLINT 存储枚举值
  4. 应用层外键:无物理外键约束,应用层保证引用完整性
  5. 索引策略:合理使用 B-Tree、GIN、部分索引
  6. 触发器:自动更新 updated_at 字段
  7. 注释规范:完整的表级和列级注释

支持文档中定义的所有功能

  1. 文件解析状态管理

    • idle (0) - 未解析
    • pending (1) - 待解析
    • parsing (2) - 解析中
    • completed (3) - 已完成
    • failed (4) - 失败
  2. 多种剧本类型

    • type=1 (file) - 上传文件
    • type=2 (manual) - 手动输入
  3. 文件格式支持

    • TXT、Markdown(同步解析)
    • DOCX、PDF、RTF、DOC(异步解析)
  4. 全文搜索

    • 剧本名称搜索
    • 剧本内容搜索
    • 元素名称搜索
    • 标签名称搜索

表结构概览

screenplays 表

screenplay_id (UUID v7, PK)
├── project_id (UUID)
├── name (TEXT)
├── type (SMALLINT: 1=file, 2=manual)
├── file_url, file_name, file_size, mime_type (文件信息)
├── content (TEXT, Markdown)
├── word_count (INTEGER)
├── parsing_status (SMALLINT: 0-4)
├── parsing_error (TEXT)
├── parsed_at (TIMESTAMPTZ)
├── display_order (INTEGER)
├── created_at, updated_at, deleted_at (TIMESTAMPTZ)

索引:7 个(包括 2 个全文搜索索引)
约束:4 个(类型、状态、字数、内容完整性)
触发器:1 个(自动更新 updated_at)

screenplay_tags 表

tag_id (UUID v7, PK)
├── screenplay_id (UUID)
├── element_type (SMALLINT: 1=character, 2=scene, 3=prop, 4=sound, 5=other)
├── element_name (TEXT)
├── tag_label (TEXT)
├── description (TEXT)
├── metadata (JSONB)
├── display_order (INTEGER)
├── created_at, updated_at (TIMESTAMPTZ)

索引:7 个(包括 2 个全文搜索索引)
约束:2 个(元素类型、唯一性)
触发器:1 个(自动更新 updated_at)

后续工作

必须完成(阻塞功能开发)

  1. 创建 Model 类

    • server/app/models/screenplay.py
    • server/app/models/screenplay_tag.py
  2. 创建 Repository 类

    • server/app/repositories/screenplay_repository.py
    • server/app/repositories/screenplay_tag_repository.py
  3. 创建 Schema 类

    • server/app/schemas/screenplay.py

可选完成(增强功能)

  1. 完善 Service 类

    • 补充 ScreenplayFileParserService 的数据库操作
    • 创建 ScreenplayService
    • 创建 ScreenplayTagService
  2. 创建 API 路由

    • server/app/api/v1/screenplays.py
    • server/app/api/v1/screenplay_tags.py
  3. 创建 Celery 任务

    • server/app/tasks/screenplay_tasks.py

测试验证

数据库迁移测试

# 升级到最新版本
docker exec jointo-server-app alembic upgrade head

# 验证表结构
docker exec jointo-server-postgres psql -U jointoAI -d jointo -c "\d screenplays"
docker exec jointo-server-postgres psql -U jointoAI -d jointo -c "\d screenplay_tags"

# 查看索引
docker exec jointo-server-postgres psql -U jointoAI -d jointo -c "\di screenplays*"
docker exec jointo-server-postgres psql -U jointoAI -d jointo -c "\di screenplay_tags*"

# 降级测试
docker exec jointo-server-app alembic downgrade -1
docker exec jointo-server-app alembic upgrade head

约束测试

-- 测试类型约束(应失败)
INSERT INTO screenplays (screenplay_id, project_id, name, type)
VALUES (gen_random_uuid(), gen_random_uuid(), 'Test', 3);

-- 测试内容完整性约束(应失败)
INSERT INTO screenplays (screenplay_id, project_id, name, type)
VALUES (gen_random_uuid(), gen_random_uuid(), 'Test', 1);

-- 测试唯一约束(应失败)
INSERT INTO screenplay_tags (tag_id, screenplay_id, element_type, element_name, tag_label)
VALUES 
  (gen_random_uuid(), 'xxx', 1, '孙悟空', '少年'),
  (gen_random_uuid(), 'xxx', 1, '孙悟空', '少年');

相关文档


完成日期:2026-02-03
状态 数据库迁移已完成,等待 Model/Repository/Service 实现