はじめに
ExpressでDBのSeederを使いたいと思って調べたところ、Sequelize
というライブラリがヒットしました。
今回はその使い方を調べたので、記事にしたいと思います。
環境構築
インストール
Sequelizeのライブラリをインストール
npm install sequelize
SequelizeをCLIで使うためのライブラリをインストール
npm install sequelize-cli --save-dev
MySQLを使用する場合下記も実行してください。
(ないと、migration実行時にエラーになります。)
npm install mysql2
初期化
以下のコマンドで初期化します。
npx sequelize init
実行すると、以下のファイルとフォルダが作成されます。
- config/config.json
接続設定を記載するファイルです。 - models
データベースのモデル用のファイルを配置するフォルダです。 - migrations
マイグレーション用のファイルを配置するフォルダです。 - seeders
シーダー用のファイルを配置するフォルダです。
接続設定
config/config.jsonにDB接続用の設定を記載します。
設定はdevelopmentなど環境ごとに設定できます。デフォルトで使用されるのはdevelopmentの設定となります。
{
"development": {
"username": "root",
"password": null,
"database": "database_development",
"host": "127.0.0.1",
"dialect": "mysql"
},
"test": {
"username": "root",
"password": null,
"database": "database_test",
"host": "127.0.0.1",
"dialect": "mysql"
},
"production": {
"username": "root",
"password": null,
"database": "database_production",
"host": "127.0.0.1",
"dialect": "mysql"
}
}
DBの初期化
DBにテーブルを定義し、データの挿入まで行う方法を説明します。
順番は以下になります。
- モデル作成
- マイグレーション実行
- シーダー作成
- シーダー実行
モデル作成
sequelize model:generate --name 名前 --attributes "属性"
でモデルを作成します。
モデルを作成後、マイグレーションのコマンドを実行すると、DBにモデルと同等のテーブルが作成されます。
なので、上記のコマンドは以下のように読み換えることができます。
sequelize model:generate --name テーブル名 --attributes "列定義"
モデル名とテーブル名について
テーブル名の定義は複数形にする方もいると思いますが、複数形にするとモデルの名称も複数形になります。
回避方法があれば追記したいと思います。
どなたか情報ある方コメントしていただきたいです。
モデルを作成するサンプルコマンドを下記に記載しておきます。
npx sequelize model:generate --underscored --name users --attributes "name:string, age:integer"
自動生成される列について
以下の列は自動で生成されるので、model:generate
で作成する列定義には含めない方が良いです。
- id
- created_at
- updated_at
含めてもエラーにはなりませんが、定義内容が上書きされるみたいです。
具体的に記載すると下記のようなモデルファイルが作成されます。
'use strict';
/** @type {import('sequelize-cli').Migration} */
module.exports = {
async up(queryInterface, Sequelize) {
await queryInterface.createTable('users', {
id: {
allowNull: false,
autoIncrement: true,
primaryKey: true,
type: Sequelize.INTEGER
},
id: {
type: Sequelize.INTEGER
},
// 以下省略
idが二重で定義されて、下の方の設定で上書きされるみたいです。
実行するとmodels
にモデルのファイル、migrations
にマイグレーション用のファイルが作成されます。
マイグレーションを実行
モデル作成で、作成したマイグレーションファイルを実行します。
npx sequelize db:migrate
ターミナルで、MySQLを確認すると下記のようにテーブルが作成されます。
Seederを作成
以下のコマンドでSeederを作成します。
npx sequelize seed:generate --name sample-users
上記のコマンドで作成されたSeederファイルを編集し、どういうデータを作成するかを記載します。
'use strict';
/** @type {import('sequelize-cli').Migration} */
module.exports = {
async up (queryInterface, Sequelize) {
await queryInterface.bulkInsert('users', [
{
name: "Alice",
age: 16,
created_at: new Date(),
updated_at: new Date(),
},
{
name: "Bob",
age: 30,
created_at: new Date(),
updated_at: new Date(),
},
{
name: 'Charlie',
age: 35,
created_at: new Date(),
updated_at: new Date()
},
{
name: 'Diana',
age: 28,
created_at: new Date(),
updated_at: new Date()
},
{
name: 'Evan',
age: 22,
created_at: new Date(),
updated_at: new Date()
}
]);
},
async down (queryInterface, Sequelize) {
await queryInterface.bulkDelete('users', null, {});
}
};
Seederを実行
以下のどちらかのコマンドで実行してください。
- Seederファイルを全部実行する
npx sequelize db:seed:all
- Seederファイルを個別に実行する
npx sequelize db:seed --seed ファイル名
以下のような形で挿入されます。
オプション
こちらの章では、外部キーの設定など詳細な設定方法を記載していきます。
外部キーの設定
外部キーの設定は、モデルのファイルとマイグレーションファイルに外部キーの設定を定義し、マイグレーションを行うことで設定できます。
DBの変更のみならマイグレーションファイルに設定だけで問題なさそうですが、モデルのファイルにも定義しておくとモデルを操作するときに便利になるそうです。
モデルを作成
サンプルとして、DBの初期化の続きからusersのidを外部キーに持つposts
というテーブルを作っていきたいと思います
npx sequelize model:generate --underscored --name posts --attributes "user_id:integer body:text"
modelsに外部キーを定義する
modelsのファイルに、associate
というメソッドがあるのでそこで定義します。
'use strict';
const {
Model
} = require('sequelize');
module.exports = (sequelize, DataTypes) => {
class users extends Model {
/**
* Helper method for defining associations.
* This method is not a part of Sequelize lifecycle.
* The `models/index` file will call this method automatically.
*/
static associate(models) {
// define association here
// ここで定義する
users.hasMany(models.posts, {foreignKey: 'user_id'});
}
}
users.init({
id: DataTypes.INTEGER,
name: DataTypes.STRING,
age: DataTypes.INTEGER
}, {
sequelize,
modelName: 'users',
underscored: true,
});
return users;
};
'use strict';
const {
Model
} = require('sequelize');
module.exports = (sequelize, DataTypes) => {
class posts extends Model {
/**
* Helper method for defining associations.
* This method is not a part of Sequelize lifecycle.
* The `models/index` file will call this method automatically.
*/
static associate(models) {
// define association here
posts.belongsTo(models.users, { foreignKey: 'user_id'});
}
}
posts.init({
user_id: DataTypes.INTEGER,
body: DataTypes.TEXT
}, {
sequelize,
modelName: 'posts',
underscored: true,
});
return posts;
};
マイグレーションファイルに外部キーを定義
migrations
のxxxx-create-posts.js
の方に外部キーの定義を追加します。
'use strict';
/** @type {import('sequelize-cli').Migration} */
module.exports = {
async up(queryInterface, Sequelize) {
await queryInterface.createTable('posts', {
id: {
allowNull: false,
autoIncrement: true,
primaryKey: true,
type: Sequelize.INTEGER
},
user_id: {
type: Sequelize.INTEGER,
+ references: {
+ model: 'users', // 'users'は関連するモデルのテーブル名
+ key: 'id', // 'id'は参照先のフィールド名
+ },
},
// 省略
},
async down(queryInterface, Sequelize) {
await queryInterface.dropTable('posts');
}
};
参照先のキーにINDEXを追加
参照先となるキー(サンプルで言うとusers
のid
)にINDEXを追加します。
追加しないとエラーになります。
usersのマイグレーションファイルに下記を追加してください。
'use strict';
/** @type {import('sequelize-cli').Migration} */
module.exports = {
async up(queryInterface, Sequelize) {
await queryInterface.createTable('users', {
// 省略
updated_at: {
allowNull: false,
type: Sequelize.DATE
}
});
+ await queryInterface.addIndex('users', ['id'], {
+ unique: true,
+ name: 'id_index'
+ });
},
async down(queryInterface, Sequelize) {
await queryInterface.dropTable('users');
}
};
マイグレーションを実行する
DBの初期化の続きから実行している場合、一旦マイグレーション実行前に戻します。
npx sequelize db:migrate:undo:all
その後、再度マイグレーションを実行します。
npx sequelize db:migrate
posts
のテーブル定義をMySQLで確認すると、user_idにFOREIGN KEYの定義が追加されているはずです。