Sequelize 學習筆記(11)- Migrations 遷移
一、作用
類似 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
支援引入json
或js
兩種格式( js 更加靈活)注2:
config
還支援連線遠端資料庫
node_modules/.bin/sequelize db:migrate --url 'mysql://root:[email protected]_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 版,再手動同步修改
models
和migrations
。
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