55

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

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

这通常在 MongoDB/Mongoose 中如何处理?有什么我需要注意的问题吗?

4

3 回答 3

34

在遇到这个并合理地理解迁移如何在关系数据库上工作时,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 for Nodejs 中使用中间件:

  • 在您的根应用程序脚本中设置一个应用程序变量,app.set('schemaVersion', 1)稍后将通过该变量与用户架构版本进行比较。
  • 现在确保所有用户模式也具有 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 中更新,这样他们就不会再次运行更改,除非他们再次移动到不同的版本。

于 2014-03-17T00:03:18.253 回答
13

如果您习惯于 SQL 类型迁移或类似 Rails 的迁移,那么您会发现我的 cli 工具migrate-mongoose最适合您。

它允许您使用一个up和一个down函数编写迁移,并根据迁移的成功和失败为您管理状态。

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

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

于 2016-03-30T03:28:23.983 回答
5

有两种类型的迁移:

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

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

并非所有服务都可以承受离线迁移,我推荐在线方法。

于 2017-08-15T22:36:58.043 回答