node.jsアプリで heroku から mongoLab に mongodb で繋ぐ方法
node.jsを使って作成したチャットアプリ(DevHub)を mongodb に対応した時の覚書。
やりたかったこと
- 一つの DB を複数の Model から利用したい
- Model からはそれぞれのテーブル名を定義してデータ保持したい
- Model 間の依存関係を減らしたいので Model はそれぞれライブラリ化したい
- 各Model は DB 名を意識したくない。知っているのは自分のテーブル名のみ
heroku側の設定
・heroku から mongolab を使うには heroku 上で addon を verify しておく。クレジットカード番号などが必要
・アドオンをインストールする
$ heroku addons:add mongolab:starter
package.json に mongodb を定義
- mongodb は最新では heroku 上でのインストールでエラーになったので、とりあえず 0.9.8 では上手くいった。(2012/03/28 時点)
{ "name": "DevHub", "version": "0.0.1", "dependencies": { "express": "~> 2.5.1" , "commander": "~> 0.5.2" , "ejs": "~> 0.4.3" , "socket.io": "~> 0.9.2" , "mongodb": "0.9.8" } }
- npm install する。
mongodb への接続ロジック
- DBへの接続の仕方は、ローカルでは open() で良いが、heroku では connect() を使う
- ローカルか heroku の判定は process.env.MONGOLAB_URI が存在するかどうか
- ローカルの場合は open() のコールバックで db を取得する
- heroku の場合は connect() のコールバックで db を取得する
- 受け取った db を使いたいオブジェクトに設定してあげると、db 経由で db.collection() などが叩けるようになる。
コードイメージ
- まずは db を取得する為のライブラリを作成。(lib/mongo_builder.js)
var mongo = require('mongodb'); module.exports.ready = function(db_name, callback){ if ( process.env.MONGOLAB_URI ){ // herokuの場合の処理 mongo.connect(process.env.MONGOLAB_URI, {}, function(error, db){ callback(db); }); }else{ // localの場合の処理 new mongo.Db(db_name, new mongo.Server('127.0.0.1', mongo.Connection.DEFAULT_PORT, {}), {}).open(function(err,db){ callback(db); }); } };
- 呼び出し側のコード。ready()で取得した db を利用者(Model)に渡す。
var mongo_builder = require('./lib/mongo_builder'); var chat_log = require('./lib/chat_log'); mongo_builder.ready(db_name, function(db){ chat_log.set_db(db); });
- 利用者では受け取った db に対してテーブル名を指定しつつ書き込みなどを行う。(lib/chat_log.js)
var db; var table_name = 'chat_log'; // db を受け取ってローカルに保持 module.exports.set_db = function(current_db){ db = current_db; }; // チャットメッセージ保存処理 module.exports.add = function(data){ db.collection(table_name, function(err, collection) { collection.save( data, function(){} ); }); };
- このような作りだと、利用者が増えても ready() のコールバックに設定することで同一 db の利用が容易にできる。
var mongo_builder = require('./lib/mongo_builder'); var chat_log = require('./lib/chat_log'); var text_log = require('./lib/text_log'); // 利用者を追加 mongo_builder.ready(db_name, function(db){ chat_log.set_db(db); text_log.set_db(db); // 利用者へ db 設定処理を追加 });
おまけ
- ちなみに、heroku 上で日本時間にするには以下を叩く。
$ heroku config:add TZ=Asia/Tokyo
- mongolab のHP