2016/11/24

Node.js + ORM SequelizeでPostgreSQLをCRUD操作する

普段はフロントエンドを生業としているのだが、フロントエンド一本では食っていけない。そう思ってサーバサイドに挑戦している。
まず手始めに、Node.jsからPostgreSQLに操作してみる。ただ直接SQLをいじるのはツライのでORMライブラリのSequelizeを使う。

実行環境は以下のとおり。

  • Windows7
  • PostgreSQL - 9.4.7
    • さくらのクラウド データベースアプライアンス
  • Node.js >= 6.0
  • sequelize - 3.27.0
    • PromiseベースのORMライブラリ
  • pg - 6.1.0
    • PostgreSQLのNode.js用クライアント



データベース(PostgreSQL)を用意する


さくらのクラウドのデータベースアプライアンスのPostgreSQLを使う。
現在はPreview版ということもあり、無料で使えるのでありがたく使わせてもらう。
(もちろん自前でPostgreSQLをインストールしてもOK)

データベースは、PostgreSQLの9.4.7。
デフォルトユーザは、データベース名にも使われる。今回は「develop
接続先スイッチは、スイッチ配下に繋ぐことが多いが、今回は実験ということもあり共有セグメントに接続する。
WEB UIは、有効にするとphpPgAdminが使えるようになり、Webブラウザからデータベースの管理・操作ができるようになる。



Sequelizeを使ってDBを操作する


SequelizeはPromiseベースのORMライブラリ。今回はPostgreSQLで使うが、他にもMySQL、MariaDB、SQLite、MSSQLで利用することができる。
ORM(Object-Relational Mapping)は、SQLを直接書くより自由度は低いが、データベースの違いを吸収し、SQLを書かずにデータのCRUDができる。
(MongoDBだとMongooseとかが有名)

ライブラリのインストール


# ORM Library
$ npm i -S sequelize

# PostgreSQL client
$ npm i -S pg


コネクションの設定


PostgreSQLに接続するための設定を行なう。
const Sequelize = require('sequelize');

const sequelize = new Sequelize('develop(データベース名)', 'develop(ユーザ名)', 'パスワード', {
   host: 'IPアドレス',
   dialect: 'postgres' 
});


モデルの定義


テーブルのフィールドを定義する。その他の型については公式ドキュメントのData types参照。
freezeTableName: trueを指定すると、モデル名をそのままテーブル名として扱ってくれる。これがないと「user」というモデルでテーブルを作成すると、「users」というテーブル名になってしまう。
const User = sequelize.define('user(テーブル名)', {
    // フィールド名
    firstName: {
        // フィールドの型
        type: Sequelize.STRING,
        // DB上のフィールド名
        field: 'first_name'
    },
    lastName: {
        type: Sequelize.STRING
    }
}, {
    // モデル名をそのままテーブル名として使う
    freezeTableName: true
});


テーブルの作成


モデル名.sync()でテーブルが作成される。実行時に毎回テーブルを作成し直したい場合は、.sync({ force: true })というオプションを付ける。そうするとテーブルを一旦DROPしてからCREATE TABLEしてくれる。
User.sync().then(() => {
    console.log('created table')
});



SequelizeでCRUD


最初にNode.jsのコード、次にそのコードが実行されたときのSQLを載せていく。

登録: INSERT INTO


User.create({
    firstName: 'Rikko',
    lastName: 'BC'
}).then(result => {
    console.log('created:', result.firstName);
});
INSERT INTO
  "user"("id", "first_name", "lastName", "createdAt", "updatedAt")
VALUES
  (DEFAULT, 'Rikko', 'BC', 'Date', 'Date')
;


複数件取得: SELECT


User.findAll({
    order: [
        ['id', 'DESC']
    ]
}).then(result => {
    result.forEach(r => {
        console.log(r.id, r.firstName, r.lastName, r.createdAt);
    });
});
SELECT
  "id"
  ,"first_name" AS "firstName"
  ,"lastName"
  ,"createdAt"
  ,"updatedAt"
FROM
  "user" AS "user"
ORDER BY
  "user"."id" DESC
;


1件取得: SELECT LIMIT 1


User.findOne({
    where: { firstName: 'Rikko' }
}).then(result => {
    console.log(result.firstName, result.createdAt);
});
SELECT
  "id"
  ,"first_name" AS "firstName"
  ,"lastName"
  ,"createdAt"
  ,"updatedAt"
FROM
  "user" AS "user"
WHERE
  "user"."first_name" = 'Rikko'
LIMIT 1
;


更新: UPDATE


User.update({
    firstName: 'Rikky'
}, {
    where: {
        id: 3
    }
}).then(result => {
    console.log(result);
});
UPDATE
  "user"
SET
  "first_name" = 'Rikky'
  ,"updatedAt" = '2016-11-19 15:25:23.029 +00:00'
WHERE
  "id" = 3
;


削除: DELETE


User.destroy({
    where: {
        id: 1
    }
}).then(result => {
    console.log(result);
});
DELETE
FROM
  "user"
WHERE
  "id" = 1
;


CRUDをひと通りまとめたが、この書き方はPostgreSQLだけでなく、MySQL、MariaDB、SQLite、MSSQLでも使える。他のRDBMSを使う場合は、コネクションの設定で「dialect」に利用したいRDBMSを書くだけでよい。



参考サイト




以上

written by @bc_rikko

0 件のコメント :

コメントを投稿