用途
Convex Migrations 是一个面向 Convex 数据库的迁移与模式演进技能,适用于在 Convex 项目中新增字段、修改数据结构、回填数据、重命名字段或执行其他数据库迁移操作的场景。
迁移策略
Convex 采用“渐进式迁移”方法,核心步骤如下:
- 向模式中添加新的可选字段
- 部署同时写入旧字段和新字段的代码
- 运行迁移以回填现有数据
- 部署只使用新字段的代码
- 从模式中移除旧字段
主要能力
新增字段
- 第一步:更新模式,将新字段定义为可选字段(如
displayName: v.optional(v.string())) - 第二步:编写同时写入新旧字段的 mutation
- 第三步:编写回填迁移,使用分页查询(
paginate)批量处理,对未设置新字段的记录执行patch - 第四步:运行迁移,可通过循环调用内部 mutation 直到游标为 null,或使用
ctx.scheduler.runAfter调度异步处理
重命名字段
- 第一步:在模式中同时保留旧字段和新字段(新字段为可选)
- 第二步:写入时同时更新两个字段,读取时优先读取新字段并回退到旧字段(如
user.name ?? user.userName) - 第三步:迁移完成后,将新字段改为必填并移除旧字段
修改字段类型
以字符串转数组为例:先添加新的可选数组字段,再编写迁移将旧字符串按分隔符拆分并写入新字段,最后完成切换。
索引变更
- 添加索引:只需在模式中添加
.index(...),推送模式变更时索引会自动创建,无需迁移 - 删除索引:从模式中移除并重新部署,旧索引会自动删除
迁移进度跟踪
可定义 migrations 表记录迁移名称、开始时间、完成时间、已处理数量、状态(running/completed/failed)和错误信息,并在运行迁移前检查是否已有同名迁移正在运行,避免重复执行。
常见模式
- 软删除迁移:为记录添加
deletedAt字段 - 数据规范化:例如将邮箱地址统一转为小写
使用方式
迁移通常以 internalMutation 形式定义在 convex/migrations.ts 中,通过分页查询逐批处理数据,并使用调度器(ctx.scheduler.runAfter)在批次之间异步衔接,避免单次执行超时。
适用场景
- 为现有表添加新字段并回填历史数据
- 重命名字段并平滑过渡
- 修改字段类型(如字符串转数组)
- 添加或删除索引
- 执行软删除、数据规范化等批量数据变更
限制与注意事项
- 破坏性变更:迁移期间始终使用可选字段
- 大批量:批次大小应保持在 100 以下,避免超时
- 缺少游标:大数据集必须使用分页
- 无跟踪:应记录迁移进度以便调试
- 跳过回填:不要假设代码会永远处理缺失字段
参考
- Schema: https://docs.convex.dev/database/schemas
- Best Practices: https://docs.convex.dev/understanding/best-practices/