Sequelize 学习笔记(11)- Migrations 迁移
2020-02-10

一、作用


类似 git 管理源代码 一样,维护你的 DB。

二、安装


npm install --save sequelize-cli

三、使用


1、构建项目时

node_modules/.bin/sequelize init

会创建以下四个文件夹:

config, 包含配置文件,它告诉 CLI 如何连接数据库models,包含您的项目的所有模型migrations, 包含所有迁移文件seeders, 包含所有种子文件

问:如何修改这四个文件的位置?

答:在项目的根目录中创建一个空文件 .sequelizerc

const path = require("path");module.exports = { "config": path.resolve("config", "database.json"), "models-path": path.resolve("db", "models"), "seeders-path": path.resolve("db", "seeders"), "migrations-path": path.resolve("db", "migrations")}

注1:config 支持引入jsonjs 两种格式( js 更加灵活)

注2:config 还支持连接远程数据库

node_modules/.bin/sequelize db:migrate --url "mysql://root:password@mysql_host.com/database_name"

2、创建数据库

node_modules/.bin/sequelize db:create xxx

如果数据库已存在,会报错:

ERROR: database "xxx" already exists

3、创建模型(和迁移)

node_modules/.bin/sequelize model:generate --name User --attributes firstName:string,lastName:string,email:string

会发生:

models 文件夹中创建了一个 user 模型文件在 migrations 文件夹中创建了一个名字像 XXXXXXXXXXXXXX-create-user.js 的迁移文件

CLI 这种写法太繁琐了,一般先用 CLI 建立个 base 版,再手动同步修改 modelsmigrations

4、迁移 - 针对表结构

(1)运行所有未执行过的迁移

node_modules/.bin/sequelize db:migrate

会发生:

默认 SequelizeMeta 表中会多若干条迁移记录创建 Users

(2)撤消最近一个迁移

node_modules/.bin/sequelize db:migrate:undo

会发生:

SequelizeMeta 表的记录抹去最近的一条Users 表被删除

(3)撤消所有迁移

node_modules/.bin/sequelize db:migrate:undo:all

(4)撤消到特定的迁移

node_modules/.bin/sequelize db:migrate:undo:all --to XXXXXXXXXXXXXX-create-posts.js

默认会记录迁移的记录在数据库的 SequelizeMeta 表里(可更改,见下文)

5、种子 - 针对表数据

(1)创建种子

node_modules/.bin/sequelize seed:generate --name demo-user

会发生:

seeders 文件夹中创建一个种子文件,文件名看起来像是 XXXXXXXXXXXXXX-demo-user.js

(2)运行所有未执行过的种子

node_modules/.bin/sequelize db:seed:all

(3)撤销所有种子

node_modules/.bin/sequelize db:seed:undo:all

默认并不会记录种子的记录(可开启,见下文)

6、迁移 / 种子记录的存储

sequelize : 将迁移和种子存储在 sequelize 数据库的表中json : 将迁移和种子存储在 json 文件上none : 不存储任何迁移/种子

写法:

{ "development": { "username": "root", "password": null, "database": "database_development", "host": "127.0.0.1", "dialect": "mysql", // ------迁移存储------ // 使用不同的存储类型. Default: sequelize "migrationStorage": "json", // 使用不同的文件名. Default: sequelize-meta.json "migrationStoragePath": "sequelizeMeta.json", // 使用不同的表名. Default: SequelizeMeta "migrationStorageTableName": "sequelize_meta" // ------种子存储------ // 使用不同的存储空间. Default: none "seederStorage": "json", // 使用不同的文件名. Default: sequelize-data.json "seederStoragePath": "sequelizeData.json", // 使用不同的表名 Default: SequelizeData "seederStorageTableName": "sequelize_data" }}

我个人的习惯是迁移种子都是 sequelize

7、迁移框架

一个典型迁移文件的构成:

module.exports = { up: (queryInterface, Sequelize) => { // 转变为新状态的逻辑 // 返回一个 `Promise` }, down: (queryInterface, Sequelize) => { // 恢复更改的逻辑 // 返回一个 `Promise` }}

Sequelize 对象存储可用的数据类型

queryInterface 对象可以用来修改数据库(api:http://docs.sequelizejs.com/class/lib/query-interface.js~QueryInterface.html#instance-method-removeIndex)

8、更多 CLI 操作

node_modules/.bin/sequelize help


四、坑


1、已经事先写好了 models,但是需要从 models 生成 migrations 脚本,怎么办?

官方并不支持(见讨论:https://github.com/sequelize/cli/issues/157)

可以用第三方脚本(如:https://gist.github.com/ahelord/a7a7d293695b71aadf04157f0f7dee64)

2、同一个 migrations 脚本中存在两个及以上的枚举类型(ENUM),则执行迁移失败,怎么办?

这也是官方的一个 bug,我们可以除了第一个枚举类型用 queryInterface.createTable,其它的枚举类型请用 queryInterface.sequelize.query 这种接近原生的写法,例如:

queryInterface.sequelize.query("CREATE TYPE "enum_MemberActionlogs_newColumn" AS ENUM ("领卡", "激活", "领卷", "核销", "购物"); ALTER TABLE "MemberActionlogs" ADD COLUMN "newColumn" "enum_MemberActionlogs_newColumn";")

3、sequelize.sync() vs migrations

推荐在开发和生产环境里都使用 migrations,sync() 功能太过于单薄。

可参考:Sequelize Sync vs Migrations - Stack Overflow


参考资料:

https://demopark.github.io/sequelize-docs-Zh-CN/migrations.html