Node.js | ExpressでPostgreSQLを使う

Node.jsにはデータベースを利用したアプリケーションを作る機能もある。ここではExpressからPostgreSQLを使い、Herokuへデプロイする方法を説明する。

Node.jsからPostgreSQLを使う

データベースは多くのWebアプリケーションで重要になる。Node.jsでは標準機能だけでなく、追加パッケージを使ってデータベースへアクセスする。この記事では、Herokuが標準的に対応しているPostgreSQLを利用する。

まずローカル環境にPostgreSQLをインストールする。アプリケーションのテストやHerokuのPostgreSQLコマンドを使うためにも必要である。PostgreSQLのbinディレクトリをシステムのPathへ追加し、psqlなどのコマンドをターミナルから呼び出せるようにしておく。

C:\Program Files\PostgreSQL\x.x\bin

Node.jsアプリケーションのディレクトリで依存関係をインストールし、PostgreSQL用パッケージを追加する。

$ npm install
$ npm install pg

pgはNode.jsからPostgreSQLへアクセスするためのパッケージである。

Herokuを準備する

アプリケーションのディレクトリでHerokuへログインし、PostgreSQLアドオンを追加する。

$ heroku login
$ heroku addons:add heroku-postgresql:dev

アドオンが追加されたら、アプリケーションの標準データベースとしてpromoteする。

$ heroku pg:promote HEROKU_POSTGRESQL_NAME_URL

HerokuのPostgreSQLコンソールからテーブルを作成する。

$ heroku pg:psql

この例では、簡単なmydataテーブルを作成する。

create table mydata (
  id serial primary key,
  name char(50),
  mail char(100),
  memo char(255)
);

Heroku用のファイル

HerokuへデプロイするExpressアプリケーションには、アプリケーション情報と起動コマンドが必要になる。package.jsonにはexpresspgejsなどの依存関係を記述する。

{
  "name": "application-name",
  "version": "0.0.1",
  "private": true,
  "scripts": {
    "start": "node app.js"
  },
  "dependencies": {
    "express": "latest",
    "pg": "latest",
    "ejs": "*"
  }
}

アプリケーションのルートにProcfileを作成する。

web: node app.js

app.jsでルーティングする

この例ではトップページのほか、入力フォーム用の/addと、POST処理用の/createを用意する。

var add = require("./routes/add");
var create = require("./routes/create");

app.use("/add", add);
app.use("/create", create);

テーブルのレコードを表示する

トップページではroutes/index.jsviews/index.ejsを使う。pg.connectでPostgreSQLへ接続し、select * from mydataを実行する。rowイベントで行を集め、endイベントでテーブルを描画する。

var con = "tcp://user:password@host:port/database";
pg.connect(con, function(err, client) {
  var query = client.query("select * from mydata;");
  var rows = [];
  query.on("row", function(row) {
    rows.push(row);
  });
  query.on("end", function() {
    response.render("index", { title: "Express", data: rows });
  });
});

テンプレート側ではdataをループし、各レコードのnamemailmemoをテーブルに表示する。

SQLクエリを実行する

データベースアクセスは、接続してからclient.queryを呼び出す形が基本である。

var query = client.query("select * from mydata;");

queryQueryオブジェクトを返す。処理は非同期で行われるため、SELECT結果の行が直接戻り値として返るわけではない。検索結果、完了、エラーはrowenderrorイベントで扱う。

レコードを追加する

追加ページはadd.ejsadd.jscreate.jsで構成する。フォームはnamemailmemo/createへ送信する。

<form method="post" action="/create">
  <input type="text" name="name">
  <input type="text" name="mail">
  <input type="text" name="memo">
  <input type="submit">
</form>

POSTハンドラではrequest.bodyから値を読み、INSERT文を実行し、完了後にトップページへリダイレクトする。

var qstr = "insert into mydata (name,mail,memo) values($1, $2, $3);";
var query = client.query(qstr, [name_str, mail_str, memo_str]);

query.on("end", function() {
  response.redirect("/");
});

$1$2$3のプレースホルダには、第2引数の配列の値が順に渡される。このパターンを理解しておけば、データベースへ接続し、SQLをqueryで実行し、イベントで結果を処理するという流れで、基本的なデータベース操作を実装できる。