如何正确处理mongoose模式迁移?

时间:2013-08-18 03:20:05

标签: mongodb mongoose

我对MongoDB& Mongoose似乎无法找到关于如何在架构更改时处理迁移的答案。

我习惯于运行迁移SQL脚本来改变表结构和需要更改的任何底层数据。这通常涉及数据库停机时间。

这通常如何在MongoDB / Mongoose中处理?我需要注意哪些问题?

3 个答案:

答案 0 :(得分:21)

通过了解并合理地理解迁移在关系数据库上的工作方式,MongoDB使这一点变得更加简单。我有两种方法来打破这种局面。在处理MongoDB中的数据迁移时要考虑的事情(并非RDB中不常见):

  • 当开发人员合并项目存储库中的最新版本时,确保本地测试环境不会中断
  • 确保在实时版本上正确更新任何数据,无论用户是否已登录或注销,如果使用身份验证。 (当然,如果每个人在升级时自动退出,那么只需要担心用户何时登录)。

1)如果您的更改会将所有人都记录下来或预计应用程序停机,那么执行此操作的简单方法是使用迁移脚本连接到本地或实时MongoDB并升级正确的数据。用户名从单个字符串更改为具有给定名称和族名的对象的示例(当然非常基本,需要放入脚本以便为所有开发人员运行):

使用CLI:

mongod
use myDatabase
db.myUsers.find().forEach( function(user){
    var curName = user.name.split(' '); //need some more checks..

    user.name = {given: curName[0], family: curName[1]};
    db.myUsers.save( user );
})

2)您希望应用程序根据它们运行的​​应用程序版本上下迁移模式。这显然不会对实时服务器造成负担,并且由于仅在第一次使用升级/降级版本时仅升级用户而不需要停机时间。

如果您在Expressjs中使用Nodejs中的中间件:

  • 通过app.set('schemaVersion', 1)在根应用程序脚本中设置app变量,稍后将使用该变量与用户架构版本进行比较。
  • 现在确保所有用户模式都具有schemaVersion属性,因此我们可以检测应用程序模式版本与仅特定用户的当前MongoDB模式之间的更改。
  • 接下来,我们需要创建简单的中间件来检测配置和用户版本

    app.use( function( req, res, next ){
      //If were not on an authenticated route
      if( ! req.user ){
        next();
        return;
      }
      //retrieving the user info will be server dependent
      if( req.user.schemaVersion === app.get('schemaVersion')){
        next();
        return;
      }
    
      //handle upgrade if user version is less than app version
    
      //handle downgrade if user version is greater than app version
    
      //save the user version to your session / auth token / MongoDB where necessary
    })
    

对于升级/降级,我将使用升级/降级导出功能在迁移目录下创建简单的js文件,这些函数将接受用户模型并在MongoDB中对该特定用户运行迁移更改。最后确保在MongoDB中更新用户版本,这样他们就不会再次运行更改,除非他们再次转移到其他版本。

答案 1 :(得分:3)

如果您已经习惯了SQL类型的迁移或类似Rails的迁移,那么您将找到适合您的cli工具migrate-mongoose

它允许您使用updown功能编写迁移,并根据迁移的成功和失败为您管理状态。

如果您使用ES 2015语法,它还支持ES6。

您可以通过this对象访问您的mongoose模型,从而可以轻松地对模型和模式进行更改。

答案 2 :(得分:3)

有两种类型的迁移:

  • 离线:将要求您停止维护服务,然后遍历整个集合并进行所需的更改。

  • 在线:不需要停止维修。阅读文档时,检查其版本,并为旧版本和新版本之间的每个版本运行特定于版本的迁移例程。然后加载生成的东西。

并非所有服务都能提供离线迁移,我建议使用在线方法。