用 migrate-mongo 做 MongoDB 迁移可行但需手动管理连接与错误处理:每次迁移脚本须独立建连并显式 close;up/down 前需判断集合/索引存在性;必须 try/catch 全逻辑并 throw 错误,否则 migrations 集合会误标成功。

直接说结论:用 migrate-mongo 做 MongoDB 迁移是可行的,但必须手动管理 mongod 连接生命周期,且不能依赖它自动处理并发或回滚失败的迁移。
为什么 migrate-mongo 的 up 和 down 不会自动重连?
它默认复用同一个 MongoClient 实例,但迁移脚本执行完后连接不会自动关闭;若你在 up.js 里调用 db.close(),后续 down.js 就会报 Topology was destroyed 错误。
- 每次迁移脚本(
up.js/down.js)都应独立获取连接,用完立刻client.close() - 不要在
migrate-mongo-config.js里导出已初始化的client,只导出连接配置(url、databaseName) -
migrate-mongo本身不封装连接池逻辑,它只负责按序执行脚本并记录migrations集合
如何写一个安全的 up.js 脚本?
典型错误是直接操作 db 却忽略集合是否存在、索引是否已建,导致重复运行时报错。
- 所有集合操作前加
await db.listCollections({ name: 'users' }).toArray()判断存在性 - 创建索引时用
createIndex(..., { background: true, unique: false }),避免阻塞 - 批量更新务必加
{ multi: true }(MongoDB 4.x+ 可用updateMany) - 示例片段:
module.exports = { async up(db, client) { const users = db.collection('users'); await users.updateMany( { status: 'active' }, { $set: { lastActiveAt: new Date() } } ); await client.close(); // 必须显式关闭 } };
migrate-mongo 的 migrations 集合怎么被污染?
当某个迁移脚本抛出未捕获异常(比如 db.collection(...).findOne is not a function),migrate-mongo 仍会把该迁移标记为 “success” 并写入 migrations 集合 —— 下次 up 就跳过它,数据状态和迁移记录彻底不一致。
- 每个
up.js必须用try/catch包裹全部逻辑,并在catch中throw明确错误 - 不要依赖
console.error,migrate-mongo不解析 stdout/stderr - 检查
migrations集合内容:db.getCollection('migrations').find().sort({ _id: -1 }),确认status字段值为"success"或"error" - 若发现脏数据,可手动删除对应文档再重试,但需先备份业务数据
真正麻烦的不是写迁移脚本,而是验证每一步是否幂等、连接是否干净、失败后能否人工介入。别指望 migrate-mongo 替你兜底。


















