1. 程式人生 > >Sequelize 學習筆記(11)- Migrations 遷移

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 支援引入jsonjs 兩種格式( 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 版,再手動同步修改 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