Groovy で MongoDB を使用

ドキュメント指向DBであるMongoDBを軽く使ってみました。
環境は以下の通り。

  • MongoDB 1.3.1
  • MongoDB Java Driver 1.2
  • Groovy 1.7.0

MongoDBの起動

MongoDB のアーカイブをダウンロード・解凍、bin ディレクトリを環境変数 PATH に設定して mongod コマンドを実行すれば MongoDB サーバーが起動します。

起動例(カレントの db ディレクトリを使用)
>mongod -dbpath db
Sat Feb 20 12:00:00 Mongo DB : starting : pid = 0 port = 27017 dbpath = db master = 0 slave = 0  32-bit
・・・

ドキュメントの追加

MongoDB ではドキュメント(オブジェクト)をコレクションに追加していきます。
なお、MongoDB Java Driver では DBCollection オブジェクトに DBObject を追加する事になります。

今回作ったサンプルの処理の流れは以下の通り。

  1. 接続先を指定して Mongo オブジェクト作成
  2. Mongo オブジェクトから DB 取得
  3. DB から DBCollection 取得
  4. DBCollection に DBObject 追加

なお、DBObject オブジェクトを作成する方法はいろいろと用意されていそうですが、今回は以下の 3点を試してみました。

  • BasicDBObject をインスタンス
  • BasicDBObjectBuilder を使用
  • JSONParser を使用
add_data.groovy
import com.mongodb.*
import com.mongodb.util.JSONParser

def con = new Mongo("localhost")
def db = con.getDB("local")
//コレクションの取得(無かったら新規作成される)
def col = db.getCollection("test-col")

(1..5).each {
    println it

    //BasicDBObject をインスタンス化
    def doc = new BasicDBObject()
    doc.put("no", it)
    doc.put("title", "テストデータ" + it)

    //BasicDBObjectBuilder を使って Map から BasicDBObject を生成
    details = BasicDBObjectBuilder.start(["value": it * it, "category": "A"]).get()
    doc.put("details", details)

    //ドキュメント追加
    col.insert(doc)
}

//JSONParser を使って JSON 文字列から BasicDBObject を生成
def json = new JSONParser("{'no': 6, 'title': 'test6'}")
//ドキュメント追加
col.insert(json.parseObject())

実行例は以下の通り。環境変数 CLASSPATH に mongo-1.2.jar を追加しておく点に注意。

実行例
>groovy add_data.groovy

ちなみに、追加したドキュメントの構造は基本的に以下のようになっている。(no:1 の場合)

  • no: 1
  • title: テストデータ1
  • details:
    • value: 1
    • category: A

ドキュメントの検索

それでは、先程追加したデータの確認を兼ねて検索してみます。検索には find メソッドを使用し、検索条件を DBObject で作成します。
基本的に対象フィールド名と条件値を指定すれば良いようです。

なお、ドキュメントが階層構造を成している場合はドット「.」でフィールド名を繋げて指定すればいいみたいです。(例えば、details 内の value の値を検索条件にしたい場合は details.value に対して値を指定する)

find_data.groovy
import com.mongodb.*

def con = new Mongo("localhost")
def db = con.getDB("local")
def col = db.getCollection("test-col")

//全取得
println "------- ALL ---------"
col.find().each {
    println it
}

//no=5 を取得
println "------- no=5 ---------"
col.find(new BasicDBObject("no", 5)).each {
    println it
}

//details の value が 10 より小さいものを取得(value < 10)
println "------- value < 10 ---------"
def query = new BasicDBObject("details.value", new BasicDBObject('$lt', 10))
col.find(query).each {
    println it
}

実行結果は以下の通り。

実行結果
>groovy find_data.groovy
------- ALL ---------
[_id:4b7f71e2ec3f996f6072845a, no:1, title:テストデータ1, details:[value:1, category:A], _ns:test-col]
[_id:4b7f71e2ec3f996f6172845a, no:2, title:テストデータ2, details:[value:4, category:A], _ns:test-col]
[_id:4b7f71e2ec3f996f6272845a, no:3, title:テストデータ3, details:[value:9, category:A], _ns:test-col]
[_id:4b7f71e2ec3f996f6372845a, no:4, title:テストデータ4, details:[value:16, category:A], _ns:test-col]
[_id:4b7f71e2ec3f996f6472845a, no:5, title:テストデータ5, details:[value:25, category:A], _ns:test-col]
[_id:4b7f71e2ec3f996f6572845a, no:6, title:test6, _ns:test-col]
------- no=5 ---------
[_id:4b7f71e2ec3f996f6472845a, no:5, title:テストデータ5, details:[value:25, category:A], _ns:test-col]
------- value < 10 ---------
[_id:4b7f71e2ec3f996f6072845a, no:1, title:テストデータ1, details:[value:1, category:A], _ns:test-col]
[_id:4b7f71e2ec3f996f6172845a, no:2, title:テストデータ2, details:[value:4, category:A], _ns:test-col]
[_id:4b7f71e2ec3f996f6272845a, no:3, title:テストデータ3, details:[value:9, category:A], _ns:test-col]