九保すこひ@フリーランスエンジニア|累計300万PVのブログ運営中
さてさて、前々回の「入門!Expressのインストールと基本のまとめ」でも少し書いたのですが、Node.js
のフレームワーク「Express」を本格的に使ってみた実感として、Laravel
のようなデータベース周りの機能がなく、ちょっと残念な気持ちになっていました。
ところが、やはり世界中には天才プログラマーたちが多数いるもので、Node.js
に以下3つの機能を一気に提供してくれるパッケージがあることを知りました。
- マイグレーション ・・・ DBテーブルの管理
- Seed ・・・ テストデータの管理
- モデル ・・・ データベース操作(
Laravel
のEloquent
のようなもの)
その名も「Sequelize」です。
※ YouTube
を見る限り、「すぃーくぅらいず」と読むようです。英語でSQL
を「すぃーくぅ(る)」と読むことに掛けてるのかと思います。
しかもこのパッケージには、Laravel
のartisan
コマンドのように各ファイルを自動的に作成してくれるクライアント用パッケージもあるので、これを使えば一気に開発スピードが上げること間違いなしです。
そこで!
今回は、Node.js
のパッケージ「Sequilize」の使い方をご紹介したいと思います。
ぜひ皆さんのお役に立てると嬉しいです😊✨
開発環境: Node.js 8.10、Express 4.1、Sequelize 5.2
目次
インストールする
まずはパッケージのインストールですが、「Sequelize」本体とコマンド入力が使えるようになる「sequelize–cli」、そして今回はデータベースにMySQL
を使いますので「mysql2」の3つをインストールします。
まずは、ターミナルでsequelize
を使いたいプロジェクトのフォルダに移動して以下のコマンドを実行してください。
本体・・・プロジェクト内にインストール
npm install --save sequelize
CLI・・・ グローバル環境にインストール
sudo npm install -g sequelize-cli
※ 今後どのフォルダからでも使えるようにしたいのでグローバル環境にインストールしています。
MySQL
npm install --save mysql2
※ もし別のDBを使いたい場合は以下を参照してください。
PostgreSQL
npm install --save pg pg-hstore
MariaDB
npm install --save mariadb
SQLite
npm install --save sqlite3
SQL Server
npm install --save tedious
準備する
インストールが完了したら、以下のコマンドで初期化をしておきましょう。
npx sequelize-cli init
すると、以下4つのフォルダがプロジェクト内に作成されます。
- seeders
- models
- migrations
- config
では、「config」フォルダ内に「config.json」というファイルが作成されているので、中身を開いてデータベース接続情報を書き込んでおきましょう。
(今回は開発環境のdevelopment
だけ変更しますが、テスト環境のtest
、本番環境のproduction
もお好みで変更してください)
{ "development": { "username": "root", "password": "********", "database": "express41", "host": "127.0.0.1", "dialect": "mysql", "operatorsAliases": 0 }, "test": { "username": "root", "password": null, "database": "database_test", "host": "127.0.0.1", "dialect": "mysql", "operatorsAliases": 0 }, "production": { "username": "root", "password": null, "database": "database_production", "host": "127.0.0.1", "dialect": "mysql", "operatorsAliases": 0 } }
※ 実行環境の切り替えは、process.env.NODE_ENV
の値を変更すればOKです。.env
を使って変更する場合は、Node.jsで.envを使う方法をご覧ください。
※ また、operatorsAliases
をfalse
にしていて警告が出る場合は0
に変更してください。
マイグレーションを使う
マイグレーションとは、ざっくり言うと「簡単にDBテーブルを構築できる」機能のことです。ひとつずつ見ていきましょう。
テーブルをつくる
例えば、Users
という名前のテーブルをDBにつくる(and 削除する)マイグレーションのファイルを作成するには以下のコマンドを実行します。
npx sequelize-cli migration:generate --name Users
【注意!】ただし、sequelize
は、モデルを作成する際にも自動でマイグレーションを作成する仕様になっています。そのため、もしモデルも必要な場合はモデル作成のコマンドを使うことをおすすめします。(マイグレーションが重複してしまうため)実際のコマンドは、モデルを使うをご覧ください。
すると、「/migrations/********-Users.js」というファイルが作成されるので以下6つのフィールドを追加してみましょう。
- id
- name
- password
- createdAt
- updatedAt
'use strict'; module.exports = { up: (queryInterface, Sequelize) => { return queryInterface.createTable('Users', { id: { allowNull: false, autoIncrement: true, primaryKey: true, type: Sequelize.INTEGER }, name: { type: Sequelize.STRING }, email: { type: Sequelize.STRING }, password: { type: Sequelize.STRING }, createdAt: { allowNull: false, type: Sequelize.DATE }, updatedAt: { allowNull: false, type: Sequelize.DATE } }); }, down: (queryInterface, Sequelize) => { return queryInterface.dropTable('Users'); } };
そして、ファイルを保存したら以下のコマンドでマイグレーションを実行します。
npx sequelize-cli db:migrate
コマンドを実行するとDB
はこのようになります。
【データベース】
【Usersテーブル】
フィールドの設定項目
なお、フィールドで設定できる主な項目は次のとおりです。
- type ・・・ データタイプ(次の項目を参照してください)
- primaryKey ・・・ プライマリーキー(true / false)
- autoIncrement ・・・ オートインクリメント(true / false)
- unique ・・・ ユニーク、同じ値がない(true / false)
- allowNull ・・・ Nullの許可(true / false)
- defaultValue ・・・ デフォルト値
- comment ・・・ フィールドの説明
データタイプ
主なデータタイプは以下のとおりです。
- Sequelize.STRING ・・・ 文字列
- Sequelize.TEXT ・・・ テキスト
- Sequelize.INTEGER ・・・ 数字
- Sequelize.INTEGER.UNSIGNED ・・・ 数字(ゼロ以上)
- Sequelize.BIGINT ・・・ (大きい数字)
- Sequelize.FLOAT ・・・ 浮動小数点数型
- Sequelize.BOOLEAN ・・・ true / false
- Sequelize.DATE ・・・ 日時
- Sequelize.DATEONLY ・・・ 日付
FOREIGN KEY
例えば、先ほど作ったUsers
テーブルと連動するテーブルposts
のuser_id
にFOREEIGN KEY
を設定する場合は次のようにします。
'use strict'; module.exports = { up: (queryInterface, Sequelize) => { return queryInterface.createTable('posts', { id: { type: Sequelize.INTEGER.UNSIGNED, primaryKey: true, autoIncrement: true, allowNull: false }, user_id: { type: Sequelize.INTEGER, references: { model: 'Users', key: 'id'}, // 外部キー onUpdate: 'cascade', // (任意)連動して自動更新する場合 onDelete: 'cascade' // (任意)連動して自動削除する場合 } }); }, down: (queryInterface, Sequelize) => { return queryInterface.dropTable('posts'); } };
インデックス
テーブルにインデックスを設定する場合は次のようにします。
'use strict'; module.exports = { up: (queryInterface, Sequelize) => { return queryInterface.createTable('posts', { // 省略 }).then(() => { // インデックスを追加 return queryInterface.addIndex('posts', ['user_id']); }); }, down: (queryInterface, Sequelize) => { return queryInterface.dropTable('posts'); } };
マイグレーションをひとつ前に戻す
例えば、「さっきマイグレーションしたけど、抜けてる項目があったからやり直したい」という場合(いわゆる、ロールバック)は以下のコマンドを実行してください。
npx sequelize-cli db:migrate:undo
マイグレーションを全て元に戻す
ひとつだけでなく、全てのマイグレーションをはじめからやり直したい場合は、こちらのコマンドです。
npx sequelize-cli db:migrate:undo:all
Seedを使う
Seed
とはDBテーブルに初期値として用意する(テスト)データです。Seed
を作っておくと、テーブルを初期化してもまた同じデータを用意することができるのでとても便利です。
データを追加する
例えば、Users
に登録するテストユーザーのデータをつくる場合です。
まずは以下のコマンドを実行してください。
npx sequelize-cli seed:generate --name test-users
すると、「/seeders/********-test-users.js」というファイルが作成されるので中身を以下のようにしてください。
'use strict'; module.exports = { up: (queryInterface, Sequelize) => { const now = new Date(); return queryInterface.bulkInsert('Users', [ { name: '太郎', email: 'taro@example.com', password: 'taro-password', createdAt: now, updatedAt: now}, { name: '次郎', email: 'jiro@example.com', password: 'jiro-password', createdAt: now, updatedAt: now}, { name: '三郎', email: 'saburo@example.com', password: 'saburo-password', createdAt: now, updatedAt: now}, { name: '四郎', email: 'shiro@example.com', password: 'shiro-password', createdAt: now, updatedAt: now}, { name: '五郎', email: 'goro@example.com', password: 'goro-password', createdAt: now, updatedAt: now}, ], {}); }, down: (queryInterface, Sequelize) => { return queryInterface.bulkDelete('Users', null, {}); } };
では、以下のコマンドを実行してSeed
を実行してみましょう。
npx sequelize-cli db:seed:all
実行が終わるとテーブルはこのようになります。
データを元に戻す
Seed
を元に戻す場合は以下のコマンドを使ってください。
npx sequelize-cli db:seed:undo:all
ただし、オートインクリメントはこの方法では初期化されないので、個人的にはnpx sequelize-cli db:migrate:undo:all
でテーブルを削除してまた実行する方がてっとり早いような気がします。
モデルを使う
データベースの操作が楽にできるようになる「データの管理人」がモデルの役目です。
モデルをつくる
例えば、User
というモデルを作成する場合です。
npx sequelize-cli model:generate --name User --attributes name:string,email:string,password:string
sequelize
は、id
、CreatedAt
、UpdatedAt
の3フィールドを自動的に作成してくれますので、それ以外を指定するだけでOKです。
すると、以下2つのファイルが作成されます。
- モデル ・・・ 「/models/user.js」
- マイグレーション ・・・ 「/migrations/*******-create-user.js」
マイグレーションの設定・実行はマイグレーションを使うを参照してください。
モデルを使う
では、Users
テーブルのデータを全て取得する場合の例を見てみましょう。アクセスするURLは「http://******/all-users」です。
「app.js」を開いて次のようにします。
const express = require('express'); const app = express(); const User = require('./models').User; // ルート app.get('/all-users', (req, res) => { User.findAll().then(users => { res.send(users); }); }); const PORT = process.env.PORT || 5000; app.listen(PORT, () => { console.log(`${PORT}番のポートで待機中です...`); });
では、npm
を再起動してブラウザから見てみましょう。
ちなみに、ブラウザからアクセスしてきたときにコンソールでは、以下のように毎回SQL文が表示されることになります。
もちろんローカル環境だと、開発にとってプラスですが本番環境では不要なものです。そのため、もしこのSQL文を非表示にしたい場合は、「/config/config.json」を開いて以下のようにするといいでしょう。
{ "development": { "username": "root", "password": "xxxxxxxx", "database": "express41", "host": "127.0.0.1", "dialect": "mysql", "operatorsAliases": 0, "logging": false }, // 省略
※ 再起動するのを忘れないでください。
【追記:2020.1.11】
モデルのより詳しい使い方は、保存版!「sequelize」モデルの使い方実例・全53件にめとめていますので、ぜひご覧ください。
おまけ:Node.jsで.envを使う方法
Laravel
でも使われている環境変数の設定システム.env
を導入して簡単に実行環境が変更になるようにしてみましょう。
まずは、パッケージをインストールします。
npm install --save dotenv
次に、ルートフォルダに.env
というファイルを作成して中身を以下のようにします。
【開発環境の場合】
NODE_ENV=development
【テスト(ステージング)環境の場合】
NODE_ENV=test
【本番環境の場合】
NODE_ENV=production
そして、「app.js」の先頭でdotenv
を読み込みます。
require('dotenv').config() const express = require('express'); const app = express(); // 以下省略
これで.env
を各環境ごとに用意すれば切り替えはOKです。(なお、git
を使ってバージョン管理する場合は忘れずに.gitignore
内に.env
を追加しておきましょう)
なお、.env
が設置されているよりも下の階層で利用する(例えば、「/test/test.js」内から.env
の内容を取得する)場合は、以下のようにpath
を指定してください。
require('dotenv').config({ path: '../.env' });
おわりに
ということで、今回はNode.js
(Express
)で「マイグレーション」、「Seed」、「モデル」が簡単に使えるようになる「Sequelize」の使い方をご紹介しました。
Laravel
をメインに開発をしている身としては、このパッケージも最初からExpress
に同梱してくれたらいいのにと思うぐらい便利なものでした。
そして、これはモデルの使い方を調べているときに感じたのですが、やはりいい設計思想は他のプログラムにも影響をするので、(どちらが先かは知りませんが)やはりLaravel
と似ている部分があったりします。以前使ったことがあるPython
のフレームワークでも同じように感じたことがあるので、「良い開発設定」は言語が違えど同じ方法を向いているような気がしました。
ということは、ひとつのフレームワークを学習すれば他の言語のフレームワークであっても習得は早くなっているといっていいと思います。流れとしては嬉しいですね😊✨
ぜひ、みなさんも「Sequelize」を試してみてくださいね。
ではでは〜!