mongodb 如何正确处理猫鼬模式迁移?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/18295357/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to properly handle mongoose schema migrations?
提问by hafichuk
I'm completely new to MongoDB & Mongoose and can't seem to find an answer as to how to handle migrations when a schema changes.
我对 MongoDB 和 Mongoose 完全陌生,似乎无法找到有关在架构更改时如何处理迁移的答案。
I'm used to running migration SQL scripts that alter table structure and any underlying data that needs to be changed. This typically involves DB downtime.
我习惯于运行迁移 SQL 脚本来更改表结构和任何需要更改的基础数据。这通常涉及数据库停机。
How is this typically handled within MongoDB/Mongoose? Any gotcha's that I need to be aware of?
这在 MongoDB/Mongoose 中通常是如何处理的?有什么我需要注意的问题吗?
回答by Ryan Q
In coming across this and reasonably understanding how migrations work on a relational database, MongoDB makes this a little simpler. I've come to 2 ways to break this down. The things to consider when dealing with data migrations in MongoDB (not all that uncommon from RDBs) are:
在遇到这一点并合理理解迁移如何在关系数据库上工作时,MongoDB 使这变得更简单一些。我有两种方法可以解决这个问题。在处理 MongoDB 中的数据迁移时要考虑的事情(并非所有 RDB 中都不常见)是:
- Ensuring local test environments do not break when a developer merges the latest from the project repository
- Ensuring any data is correctly updated on the live version regardless if a user is logged in or out if authentication is used. (Of course if everyone is automatically logged out when an upgrade is made, then only worrying about when a user logs in is necessary).
- 确保本地测试环境在开发人员从项目存储库中合并最新版本时不会中断
- 确保在实时版本上正确更新任何数据,无论用户是登录还是注销,如果使用身份验证。(当然,如果升级时所有人都自动退出,那么只需要担心用户何时登录是必要的)。
1) If your change will log everyone out or application downtime is expected then the simple way to do this is have a migration script to connect to local or live MongoDB and upgrade the correct data. Example where a user's name is changed from a single string to an object with given and family name (very basic of course and would need to be put into a script to run for all developers):
1) 如果您的更改会导致所有人注销或预计应用程序会停机,那么执行此操作的简单方法是使用迁移脚本连接到本地或实时 MongoDB 并升级正确的数据。将用户名从单个字符串更改为具有给定和姓氏的对象的示例(当然是非常基本的,需要放入脚本中才能为所有开发人员运行):
Using the CLI:
使用 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) You want the application to migrate the schemas up and down based on the application version they are running. This will obviously be less of a burden for a live server and not require down time due to only upgrading users when they use the upgraded / downgraded versions for the first time.
2) 您希望应用程序根据它们正在运行的应用程序版本上下迁移模式。这对于实时服务器来说显然会减轻负担,并且不需要停机时间,因为只有在用户第一次使用升级/降级版本时才升级用户。
If your using middleware in Expressjs for Nodejs:
如果您在 Expressjs for Nodejs 中使用中间件:
- Set an app variable in your root app script via
app.set('schemaVersion', 1)
which will be used later to compare to the users schema version. - Now ensure all the user schemas have a schemaVersion property as well so we can detect a change between the application schema version and the current MongoDB schemas for THAT PARTICULAR USER only.
Next we need to create simple middleware to detect the config and user version
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 })
- 在您的根应用程序脚本中设置一个应用程序变量,
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 })
For the upgrade / downgrade I would make simple js files under a migrations directory with an upgrade / downgrade export functions that will accept the user model and run the migration changes on that particular user in the MongoDB. Lastly ensure the users version is updated in your MongoDB so they don't run the changes again unless they move to a different version again.
对于升级/降级,我将在迁移目录下制作简单的 js 文件,并带有升级/降级导出功能,该功能将接受用户模型并在 MongoDB 中对特定用户运行迁移更改。最后确保 MongoDB 中的用户版本已更新,以便他们不会再次运行更改,除非他们再次移动到不同的版本。
回答by mrBorna
If you're used to SQL type migrations or Rails-like migrations then you'll find my cli tool migrate-mongoosethe right fit for you.
如果您习惯于 SQL 类型迁移或类似 Rails 的迁移,那么您会发现我的 cli 工具migrate-mongoose非常适合您。
It allows you to write migrations with an up
and a down
function and manages the state for you based on success and failure of your migrations.
它允许您使用up
和down
函数编写迁移,并根据迁移的成功和失败为您管理状态。
It also supports ES6 if you're using ES 2015 syntax.
如果您使用 ES 2015 语法,它还支持 ES6。
You get access to your mongoose models via the this
object, making it easy to make the changes you need to your models and schemas.
您可以通过this
对象访问 mongoose 模型,从而轻松对模型和模式进行所需的更改。
回答by arboreal84
There are 2 types of migrations:
有两种类型的迁移:
Offline: Will require you to take your service down for maintenance, then iterate over the entire collection and make the changes you need.
Online: Does not require to take your service down for maintenance. When you read the document, you check its version, and run a version specific migration routine for each version between the old and the new. Then you load the resulting thing.
离线:将要求您关闭服务进行维护,然后迭代整个集合并进行所需的更改。
在线:不需要关闭您的服务进行维护。当您阅读该文档时,您会检查其版本,并针对新旧版本之间的每个版本运行特定于版本的迁移例程。然后你加载结果。
Not all services can afford an offline migration, I recommend the online approach.
并非所有服务都能负担得起离线迁移,我推荐在线方法。