tw项目中用的是mongo数据库,数据的迁移也是需求的一部分。这时我们可以使用migrate-mongo在nodejs中方便的进行数据的迁移,以下记录一下使用的过程。
一、migrate-mongo的使用
全局安装:npm install -g migrate-mongo,在项目中也可以局部安装:npm install migrate-mongo。
运行migrate-mongo,可以看到migrate-mongo支持以下的命令:
- init initialize a new migration project
- create [options] [description] create a new database migration with the provided description
- up [options] run all unapplied database migrations
- down [options] undo the last applied database migration
- status [options] print the changelog of the database
现在我们就来实践一下,来体验migrate-mongo的使用。首先我们创建一个目录,存放migration的脚本。
~/Program/javascript/node/2018-06-07/learn-node/node1> mkdir migrations ~/Program/javascript/node/2018-06-07/learn-node/node1> cd migration
我们的mongodb里面customer表的数据如下:
/* 1 */ { "_id" : ObjectId("5b6d4ea91eb211b1c51600f8"), "firstName" : "Alice", "lastName" : "Smith", "_class" : "com.thoughtworks.springcloud.entity.Customer" } /* 2 */ { "_id" : ObjectId("5b6d4ea91eb211b1c51600f9"), "firstName" : "Bob", "lastName" : "Smith", "_class" : "com.thoughtworks.springcloud.entity.Customer" }
创建migration的配置文件:migrate-mongo init,生成的config.js内容配置,其中mogodb的地址是本地,数据库名为huhx。
'use strict'; module.exports = { mongodb: { url: 'mongodb://localhost:27017', databaseName: "huhx", options: { useNewUrlParser: true, // removes a deprecation warning when connecting // connectTimeoutMS: 3600000, // increase connection timeout to 1 hour // socketTimeoutMS: 3600000, // increase socket timeout to 1 hour } }, // The migrations dir, can be an relative or absolute path. Only edit this when really necessary. migrationsDir: 'migrations', // The mongodb collection where the applied changes are stored. Only edit this when really necessary. changelogCollectionName: 'changelog', };
然后我们创建我们的迁移脚本,在表里面加上一个更新lastname=Smith的值为hu。
~/Program/javascript/node/2018-06-07/learn-node/node1/migrations> migrate-mongo create addfullnamefield Created: migrations/20180915084157-addfullnamefield.js
我们编写20180915084157-addfullnamefield.js的内容如下:
'use strict'; module.exports = { up(db) { // TODO write your migration here const customerList = db.collection('customer').find({firstName: 'Alice'}); return customerList.forEach(item => { const fullName = `${item.firstName} ${item.lastName}`; db.collection('customer').updateOne({_id: item._id}, {$set: {fullName: fullName}}, {multi: 1}); }); }, down(db) { // TODO write the statements to rollback your migration (if possible) return db.collection('customer').updateMany({firstName: 'Alice'}, {$unset: {fullName: ''}}); } };
此时我们可以使用migrate-mongo status命令来查看migrate的状态:
运行migrate-mongo up正式执行migration。如下所示
~/Program/javascript/node/2018-06-07/learn-node/node1/migrations> migrate-mongo up MIGRATED UP: 20180915084157-addfullnamefield.js
此时我们可以看到在huhx的数据库,可以看到changelog的collection。里面的内容如下:
{ "_id" : ObjectId("5b9ccd21adbd49b60990f0b8"), "fileName" : "20180915084157-addfullnamefield.js", "appliedAt" : ISODate("2018-09-15T09:13:05.272Z") }
而且我们的customer中的数据,也相应的得到了迁移处理。
/* 1 */ { "_id" : ObjectId("5b6d4ea91eb211b1c51600f8"), "firstName" : "Alice", "lastName" : "Smith", "_class" : "com.thoughtworks.springcloud.entity.Customer", "fullName" : "Alice Smith" } /* 2 */ { "_id" : ObjectId("5b6d4ea91eb211b1c51600f9"), "firstName" : "Bob", "lastName" : "Smith", "_class" : "com.thoughtworks.springcloud.entity.Customer" }
需要注意的是关于up的函数:
function up(db) { /* */ }
should returnPromise
function up(db, next) { /* */ }
should callbacknext
如果我们要撤销修改,我们可以执行migrate-mongo downw命令,也就是执行我们定义的down()函数的内容,产生的效果是customer表中fullName字段删除了,而且查看changelog数据也是为空。再次运行migrate-mongo status查看状态:
最后我们也可以指定其它的配置文件,使用-f 参数。
如果我们的addfullnamefield.js文件改变了,想要重新migrate up(已经up过了)。做法是在数据库changelog中删除记录或者是重新写一个脚本,再跑一次migrate-mongo up命令。