0%

sequelize 数据库迁移命令 migrations

我们可以直接通过mysql命令将表直接建好,但是这并不是一个对多人协作非常友好的模式。在项目演进的过程中,每一个迭代都有可能对数据库数据结构进行变更,怎样跟踪每一个迭代的数据变更,并在不同的环境(开发、测试、CI)和迭代切换中快速变更数据结构呢?我们可以使用Migrations来帮我们管理数据结构的变更。

初始化 Migrations

安装sequelize-cli

1
npm i --save-dev sequelize-cli

然后运行:

1
npx sequelize init

会创建一些文件夹:

1
2
3
4
Created "config/config.json"
Successfully created models folder at "/**/models".
Successfully created migrations folder at "/**/migrations".
Successfully created seeders folder at "/**/seeders".

这样就初始化好了。

这样的话我们的项目文件会变得很凌乱,我们希望在一个文件夹中管理Sequelize Migrations相关的东西,我们可以创建一个配置文件.sequelizerc

1
2
3
4
5
6
7
8
9
10
'use strict';

const path = require('path');

module.exports = {
config: path.join(__dirname, 'database/config.json'),
'migrations-path': path.join(__dirname, 'database/migrations'),
'seeders-path': path.join(__dirname, 'database/seeders'),
'models-path': path.join(__dirname, 'database/models'),
};

然后运行:npx sequelize init,即可在database目录下创建对应的文件。

配置数据库

在运行migration更新数据库的时候,是需要连接数据库的(这不是废话么)。我们需要在/database/config.json中配置好我们的数据库连接信息:

1
2
3
4
5
6
7
8
9
{
"development": {
"username": "root",
"password": "***",
"database": "***",
"host": "127.0.0.1",
"dialect": "mysql"
}
}

默认使用的是development的配置,在这里配置好即可。

配置Migration文件

我们来编写项目中创建User表的Migration文件。先使用命令创建文件:

1
npx sequelize migration:generate --name=init-user

执行完毕后会在database/migrations目录下产生一个migration文件:${timestamp}-init-user.js,我们通过修改它来初始化user表:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
'use strict';

module.exports = {
// 在执行数据库升级时调用的函数,创建 users 表
up: async (queryInterface, Sequelize) => {
const { INTEGER, DATE, STRING } = Sequelize;
await queryInterface.createTable('user', {
id: { type: INTEGER, primaryKey: true, autoIncrement: true },
name: STRING(30),
age: INTEGER,
created_at: DATE,
updated_at: DATE,
});
},
// 在执行数据库降级时调用的函数,删除 users 表
down: async queryInterface => {
await queryInterface.dropTable('user');
},
};

然后执行migrate进行数据库变更:

1
npx sequelize db:migrate

执行完毕后,我们查看数据库,成功的创建了user表。

在执行完毕后,在数据库中会有个SequelizeMeta表,里面有执行的记录:

1
2
3
4
5
6
mysql> select * from SequelizeMeta;
+------------------------------+
| name |
+------------------------------+
| 20200405134957-init-user.js |
+------------------------------+

执行一次数据库更新

我们有一个相册表album,里面有名字、描述之类的字段。坑爹的产品忽然说要在album上增加一个相册封面的字段,就叫cover。得,这不是一个简单的ui变更,这要在数据库上更新字段。我们来用migrations来处理这个变更。

首先,生成一个更新的记录:

1
$ npx sequelize migration:generate --name=update-album

可以看到在/database/migrations目录下新增了个js文件:202005xxxxxxxxxxxxx-update-album.js文件。前面的那一串数字是当前创建时候的时间作为唯一性前缀,保证这个文件是唯一的,因为在执行这个更新的时候是把这个文件的名字写入到数据库中的执行记录表的。

然后我们去编辑这个js文件:

1
2
3
4
5
6
7
8
9
10
11
'use strict';

module.exports = {
up: async (queryInterface, Sequelize) => {
const {STRING} = Sequelize;
await queryInterface.addColumn('album', 'cover', STRING(100));
},
down: async (queryInterface, Sequelize) => {
await queryInterface.removeColumn('album', 'cover');
}
};

里面的up表示升级的时候执行的内容:在album表中新增一条cover的字段。down表示降级的时候执行的内容:将cover字段从album表中删除。

然后我们来执行更新:

1
$ npx sequelize db:migrate     

执行完毕后可以去数据库中查看对应的表,是可以看到cover字段已经被添加到了albuma表中了。

加入添加好了,坑爹的产品又来说我们不需要这个字段了,删除它,那我们可以很方便的降级:

1
$ npx sequelize db:migrate:undo

执行完毕后可以看到album中的cover字段消失了。nice~

更新线上数据库

需要在/database/config.json中配置好生产环境的mysql配置:

1
2
3
4
5
6
7
8
9
10
{
"production": {
"username": "root",
"password": "***",
"database": "***",
"host": "***",
"dialect": "mysql",
"operatorsAliases": false
}
}

然后运行:

1
$ npx sequelize db:migrate --env production

这样就可以更新线上的数据库了。


用了之后才慢慢有了概念,migrations提供的是一个数据库渐进式开发的管理过程。每次变更都以js文件的形式跟踪,然后执行变更或者撤销变更都变得非常方便。在执行变更的时候,也是将文件名写入migrations的变更执行记录表中。的确是很方便。

码字辛苦,打赏个咖啡☕️可好?💘