便利!Node.jsにDBマイグレーション、Seed、モデルを用意する「Sequelize」

こんにちは。フリーランス・コンサルタント&エンジニアの 九保すこひ です。

さてさて、前々回の「入門!Expressのインストールと基本のまとめ」でも少し書いたのですが、Node.jsのフレームワーク「Express」を本格的に使ってみた実感として、Laravelのようなデータベース周りの機能がなく、ちょっと残念な気持ちになっていました。

ところが、やはり世界中には天才プログラマーたちが多数いるもので、Node.jsに以下3つの機能を一気に提供してくれるパッケージがあることを知りました。

  • マイグレーション ・・・ DBテーブルの管理
  • Seed ・・・ テストデータの管理
  • モデル ・・・ データベース操作(LaravelEloquentのようなもの)

その名も「Sequelize」です。

YouTubeを見る限り、「すぃーくぅらいず」と読むようです。英語でSQLを「すぃーくぅ(る)」と読むことに掛けてるのかと思います。

しかもこのパッケージには、Laravelartisanコマンドのように各ファイルを自動的に作成してくれるクライアント用パッケージもあるので、これを使えば一気に開発スピードが上げること間違いなしです。

そこで!

今回は、Node.jsのパッケージ「Sequilize」の使い方をご紹介したいと思います。

ぜひ皆さんのお役に立てると嬉しいです😊✨

開発環境: Node.js 8.10、Express 4.1、Sequelize 5.2

インストールする

まずはパッケージのインストールですが、「Sequelize」本体とコマンド入力が使えるようになる「sequelizecli」、そして今回はデータベースに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を使う方法をご覧ください。
※ また、operatorsAliasesfalseにしていて警告が出る場合は0に変更してください。

マイグレーションを使う

マイグレーションとは、ざっくり言うと「簡単にDBテーブルを構築できる」機能のことです。ひとつずつ見ていきましょう。

テーブルをつくる

例えば、Usersという名前のテーブルをDBにつくる(and 削除する)マイグレーションのファイルを作成するには以下のコマンドを実行します。

npx sequelize-cli migration:generate --name Users

【注意!】ただし、sequelizeは、モデルを作成する際にも自動でマイグレーションを作成する仕様になっています。そのため、もしモデルも必要な場合はモデル作成のコマンドを使うことをおすすめします。(マイグレーションが重複してしまうため)実際のコマンドは、モデルを使うをご覧ください。

すると、「/migrations/********-Users.js」というファイルが作成されるので以下6つのフィールドを追加してみましょう。

  • id
  • name
  • email
  • 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テーブルと連動するテーブルpostsuser_idFOREEIGN 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は、idCreatedAtUpdatedAtの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' });
開発のご依頼お待ちしております
開発のご依頼はこちらから: お問い合わせ
どうぞよろしくお願いいたします! by 九保すこひ

おわりに

ということで、今回はNode.jsExpress)で「マイグレーション」、「Seed」、「モデル」が簡単に使えるようになる「Sequelize」の使い方をご紹介しました。

Laravelをメインに開発をしている身としては、このパッケージも最初からExpressに同梱してくれたらいいのにと思うぐらい便利なものでした。

そして、これはモデルの使い方を調べているときに感じたのですが、やはりいい設計思想は他のプログラムにも影響をするので、(どちらが先かは知りませんが)やはりLaravelと似ている部分があったりします。以前使ったことがあるPythonのフレームワークでも同じように感じたことがあるので、「良い開発設定」は言語が違えど同じ方法を向いているような気がしました。

ということは、ひとつのフレームワークを学習すれば他の言語のフレームワークであっても習得は早くなっているといっていいと思います。流れとしては嬉しいですね😊✨

ぜひ、みなさんも「Sequelize」を試してみてくださいね。

ではでは〜!

このエントリーをはてなブックマークに追加       follow us in feedly