BluemixでPostgreSQL by Composeに接続するNode.jsアプリケーションの作成

## Compose by PostgreSQLのデータベースの準備

### Composeアカウントの作成

2016年6月時点で、ComposeのサービスはまだBluemixに統合されていないので、compose.io側でアカウントを作成する必要がある。以下からアカウントを作成すること。

https://app.compose.io/signup/svelte/

### PostgreSQLのデプロイメントの作成

copmose.ioにログインし、「Create Deployment」ボタンからPostgreSQLのデプロイメントを作成する。作成したら、「Overview」タブから接続に必要な情報を確認しておく。
![conectioninfo1.png](https://qiita-image-store.s3.amazonaws.com/0/86449/4c69398e-0b1c-ec2e-a086-67e1b8bbfc2b.png)

### データベースの作成

「Brower」タブから新規のデータベースを作成することができる。ここでは、testdbデータベースを作成した。

### テーブルの作成

psql、pgAdminなど、任意のツールでテーブルを作成する。ブラウザ上からも作成可能である。ここでは、accountテーブルを作成した。
![table.png](https://qiita-image-store.s3.amazonaws.com/0/86449/a8c77e0d-b4a9-0175-cd16-054bfa5e96e5.png)

## Bluemix環境の準備

### Node.jsアプリケーションの作成

カタログの「ランタイム」カテゴリからNode.jsのアプリケーションを作成する。
![nodejs.png](https://qiita-image-store.s3.amazonaws.com/0/86449/ca9678b1-aebc-8f09-cde0-7bb3e7ab08ba.png)

### PostgreSQL by Composeサービスの作成
カタログの「データおよび分析」カテゴリから、「PostgreSQL by Compose」のサービスを作成する。
![postgresql.png](https://qiita-image-store.s3.amazonaws.com/0/86449/a6e240c4-d310-b36d-b87a-662a90653e49.png)

サービスの作成時に、compose.ioで作成したデプロイメントのユーザー名、パスワード、ホスト名、ポートが必要になるので、入力する。

### アプリケーションへのサービスのバインド

Node.jsアプリケーションにPostgreSQL by Composeのサービスをバインドする。バインドすることで、アプリケーションから接続情報を環境変数として取得できる。環境変数はアプリケーションの「環境変数」メニューで確認できる。

ローカルの開発環境でアプリケーションを実行するときは、以下のコマンドを実行して環境変数をエクスポートする。

```
export VCAP_SERVICES='{
   "user-provided": [
      {
         "name": "PostgreSQL by Compose-3c",
         "label": "user-provided",
         "credentials": {
            "username": "admin",
            "password": "****************",
            "public_hostname": "sl-us-dal-9-portal.2.dblayer.com/10594"
         }
      }
   ]
}'
```
## ローカル開発環境の準備

### Node.jsのインストール

省略。以下を参照。

https://nodejs.org/en/download/package-manager/

### CFツールのインストール

今回はCLIでデプロイを行うとする。
![cli.png](https://qiita-image-store.s3.amazonaws.com/0/86449/6be524ac-27a3-58a8-cb13-518f43eb32cb.png)

ローカル開発環境にCould Foundly CLIをインストールしておく。

https://github.com/cloudfoundry/cli/releases

### スターターコードの展開

Bluemixで「コーディングの開始」メニューからスターターコードをダウンロードしてローカル開発環境に展開。

## アプリ開発

### pgモジュールのインストール

Node.jsからPostgreSQLへの接続はpgモジュールを使用する。インストールは以下のコマンドを実施。

```
$ npm install pg --save
```
モジュールの詳細は以下を参照。

https://github.com/brianc/node-postgres

### その他必要モジュールのインストール

```
$ npm install morgan --save
```

### アプリのコード例

```app.js
// モジュールの読み込み
var express = require('express');
var logger = require('morgan');
var routes = require('./routes');

// cfenv provides access to your Cloud Foundry environment
// for more info, see: https://www.npmjs.com/package/cfenv
var cfenv = require('cfenv');

// アプリケーションの作成
var app = express();

// ミドルウェアの設定
app.use(logger('dev'));
// app.use(express.static(__dirname + '/public'));

// get the app environment from Cloud Foundry
var appEnv = cfenv.getAppEnv();

// ルーティングの設定
app.use('/', routes);

// start server on the specified port and binding host
app.listen(appEnv.port, '0.0.0.0', function() {
  // print a message when the server starts listening
  console.log("server starting on " + appEnv.url);
});
```

```routes/index.js
// 使用モジュールの読み込み
var express = require('express');
var account = require('../models/account');

// ルーターの作成
var router = express.Router();

// 応答
router.get('/', function (req, res) {
  account.select(function(err,rows) {
    res.send(rows);
  });
});

module.exports = router;
```

```models/account.js
// モジュールの読み込み
var Pool = require('pg').Pool;

// 接続情報の取得
var services = JSON.parse(process.env.VCAP_SERVICES);
var credentials = services['user-provided'][0].credentials;
var hostPort = credentials.public_hostname.split('/');
var config = {
  user: credentials.username,
  password: credentials.password,
  database: 'testdb',
  host: hostPort[0],
  port: hostPort[1],
  ssl: true,
  max: 10,
  min: 4,
  idleTimeoutMillis: 1000
};

// コネクションプールの初期化
var pool = new Pool(config);

exports.select = function(callback) {
  pool.connect(function(err, client, done) {
    if(err) {
      console.error('error fetching client from pool', err);
      return callback(err);
    }
    var sql = 'SELECT * from account';
    client.query(sql, function(err, result) {
      done();
      if(err) {
        console.error('error running query', err);
        return callback(err);
      }
      callback(null, result.rows);
    });
  });
};
```

## Bluemixへのアップロード

ローカルでの稼働に問題がなければBluemixへアップロードする。

```
$ cf login
$ cf push
```

以上。