2011年10月20日木曜日

WebSocketってなんじゃ?(Node編4 MongoDBってなんじゃ?)

今回はMongoDBの話題です。
MongoDBはいわゆるNoSQLで、BSONというJSONのバイナリ版のような形式でデータの入出力を行い、クエリなどのデータ操作をjavascriptで行うため、サーバーサイドJavascriptと非常に相性がよく、node.jsとともによく利用されているようです。

今回はこのMongoDBをnode.jsから操作してみます。

MongoDB公式サイトにあるように、yumでインストールするために、MongoDB用のyumリポジトリを追加します。
以下のファイルを作成します。
/etc/yum.repos.d/10gen.repo
[10gen]
name=10gen Repository
baseurl=http://downloads-distro.mongodb.org/repo/redhat/os/i686
gpgcheck=0


さっそく、yumでインストールします。
yum install mongo-10gen mongo-10gen-server -y


インストールが終了したら、mongodが/etc/init.d/以下にできるので、起動します。
/etc/init.d/mongod start


MongoDBのコンソールを立ち上げてみます。
$ mongo

MongoDB shell version: 2.0.0
connecting to: test
testというdbにつながったようです。
helpと入力すると、いくつかのコマンドが紹介されています。DBの一覧を見てみます。
> show dbs
local (empty)
test (empty)
localとtestというDBがあり、中身はまだ空になっています。

MongoDBは基本的にはスキーマを定義することなく、いきなりデータを保存できます。データが保存された時点でそれがスキーマになります。
以下のように、hogeというデータを保存、その直後にhogeを参照してみます。
> db.hoge.save({id:"1", name:"HOGE"});
>
> db.hoge.find();
{ "_id" : ObjectId("4e9f8ced316d58abc218dc43"), "id" : "1", "name" : "HOGE" }

このように、クエリにあたるものもすべてjavascriptで行い、結果はJSON形式で表示されます。いかにもnodeと相性がよさそうです。


それでは、このMongoDBにnode.jsからアクセスしてみます。
node.jsからMongoDBにアクセスするには、MongoDB用のパッケージモジュールを入れる必要があります。
Mongo用のモジュールはいくつかあるのですが、今回はMongooseを利用してみます。
mongooseはnpmでインストールします。
# npm install -g mongoose

> mongodb@0.9.6-22 install /usr/local/lib/node_modules/mongoose/node_modules/mongodb
> bash ./install.sh

================================================================================
=                                                                              =
=  To install with C++ bson parser do <npm --mongodb:native="" install="" mongodb="">   =
=  the parser only works for node 0.4.X or lower                               =
=                                                                              =
================================================================================
Not building native library for cygwin
Using GNU make
mongoose@2.3.5 /usr/local/lib/node_modules/mongoose
├── colors@0.5.0
├── hooks@0.1.9
└── mongodb@0.9.6-22


以下のようにmongoにデータを投入するコードを書いてみます。
#!/usr/local/bin/node

var mongoose = require('mongoose');
mongoose.connect('mongodb://localhost/memorycraft');

var Schema = mongoose.Schema;
var ItemSchema = new Schema({title:String, auther:String, price:Number, date:Date});
var Item = mongoose.model('Item', ItemSchema);

var item = new Item();
item.title = "体脂肪計タニタの社員食堂 ~500kcalのまんぷく定食~";
item.auther = "タニタ";
item.price = 1200;
item.date = new Date(2010, 1, 21);

item.save(function(err){
  if(err){
    console.log(err.message);
  }
  else{
    console.log("保存しました");
  }
});


これを実行します。
$ ./hello_mongo.js
保存しました


ここで、実際にデータが投入されているか再度mongoのコンソールで確認してみます。
$mongo
> show dbs
local (empty)
memorycraft 0.0625GB
test 0.0625GB
>
> use memorycraft
switched to db memorycraft
>
> show collections
items
system.indexes
>
> db.items.find()
{ "date" : ISODate("2010-02-20T15:00:00Z"), "price" : 1200, "auther" : "タニタ", "title" : "体脂肪計タニタの社員食堂 ~500kcalのまんぷく定食~", "_id" : ObjectId("4e9f98394699a3fb40000001") }

memorycraftというdbが増えていて、投入したデータが入っていることが確認できました。

ここで、mongodb+nodeがいいのは、データの保持の時点でJSONなので、取得結果もJSONになっていることです。
そして、上記のコードを書いたようにアクセスの結果がすべてコールバックで記述できるので、とても柔軟にコード記述ができます。
例えば以下のように別途WEBフレームワークなどを使用した場合、取得したデータをそのままレスポンスに返すことで余計な変換処理が必要なくなります。
Item.find({}, function(err, items) {
  if(!err) {
    res.json(items);
  }
});

ほんの少し触れただけですが、とても便利なことがわかりました。
まだまだいろいろいじってみようと思います。
本日は以上です。