2011年12月21日水曜日

恥ずかしくて今さら聞けない、GMongo講座 2

前回の投稿からずいぶんと時間が経ってしまいました。

いろいろとすったもんだがあったので、まあ、ちょっとアレして下さい。

で、気づいたらG* Advent Calendarの担当日になっていて、

本当はGrails2.0リリース記念で記事を一本書きたかったのですが、

若干、準備不足ということで、

今回の『恥ずかしくて今さら聞けない、GMongo講座 2』でもって、G* Advent Calendarの記事とさせて下さい。

で、これまでの『恥ずかしくて今さら聞けない、GMongo講座』ですが、以下のエントリーがあります。


これらを参考にしてください。

では、本日の内容ですが、


と同等の内容をGroovyでやります。

まあ、つまりクエリーですね。

データの準備


今日はクエリですので、データをまんべんなく準備します。ってどこかで書いた記憶ががが…

例によって、JUnit@Beforeにて準備します。

MongoTest.groovy

import com.gmongo.GMongo
import org.junit.Before
import com.mongodb.DB
import org.junit.After


    GMongo mongo

    DB db

    static List<Integer> list = [1,2,3,4,5,6,7,8,9]

    static String name = 'name'

    @Before
    public void setUp() {
        mongo = new GMongo("localhost", 27017)
        db = mongo.getDB("mydb")
        def store = db[items]
        def objects = []
        list.each { x ->
            def base = x
            list.each { y ->
                base += y
                def multiple = x * y
                objects << [
                        name : name,
                        xIndex : x,
                        yIndex : y,
                        sum : base,
                        multiple : multiple]
            }
        }
        objects.each { obj ->
            store.insert(obj)
        }
    }




これで、81個のデータを準備します。

念のため、テストデータが揃っているかテストしておきましょう。

MongoTest.groovy

import org.junit.Test
import com.gmongo.GMongo
import org.junit.Before
import com.mongodb.DB
import org.junit.After


    GMongo mongo

    DB db

    static List<Integer> list = [1,2,3,4,5,6,7,8,9]

    static String name = 'name'

    int count = 81

    @Before
    public void setUp() {
        mongo = new GMongo("localhost", 27017)
        db = mongo.getDB("mydb")
        def store = db[items]
        def objects = []
        list.each { x ->
            def base = x
            list.each { y ->
                base += y
                def multiple = x * y
                objects << [
                        name : name,
                        xIndex : x,
                        yIndex : y,
                        sum : base,
                        multiple : multiple]
            }
        }
        objects.each { obj ->
            store.insert(obj)
        }
    }

    @After
    public void tearDown() {
        db.items.remove([:])
    }

    @Test
    public void testSetUp() {
        def list = db.items.find()
        assert  list.size() == count
    }



で、テストを実行します。


はい、大丈夫そうです。

一応、念のため、登録したデータはこんな感じになっています。

1 2 3 4 5 6 7 8 9
1 sum : 2
multi : 1
sum : 4
multi : 2
sum : 7
multi : 3
sum : 11
multi : 4
sum : 16
multi : 5
sum : 22
multi : 6
sum : 29
multi : 7
sum : 37
multi : 8
sum : 46
multi : 9
2 sum : 3
multi : 2
sum : 5
multi : 4
sum : 8
multi : 6
sum : 12
multi : 8
sum : 17
multi : 10
sum : 23
multi : 12
sum : 30
multi : 14
sum : 38
multi : 16
sum : 47
multi : 18
3 sum : 4
multi : 3
sum : 6
multi : 6
sum : 9
multi : 9
sum : 13
multi : 12
sum : 18
multi : 15
sum : 24
multi : 18
sum : 31
multi : 21
sum : 39
multi : 24
sum : 48
multi : 27
4 sum : 5
multi : 4
sum : 7
multi : 8
sum : 10
multi : 12
sum : 14
multi : 16
sum : 19
multi : 20
sum : 25
multi : 24
sum : 32
multi : 28
sum : 40
multi : 32
sum : 49
multi : 36
5 sum : 6
multi : 5
sum : 8
multi : 10
sum : 11
multi : 15
sum : 15
multi : 20
sum : 20
multi : 25
sum : 26
multi : 30
sum : 33
multi : 35
sum : 41
multi : 40
sum : 50
multi : 45
6 sum : 7
multi : 6
sum : 9
multi : 12
sum : 12
multi : 18
sum : 16
multi : 24
sum : 21
multi : 30
sum : 27
multi : 36
sum : 34
multi : 42
sum : 42
multi : 48
sum : 51
multi : 54
7 sum : 8
multi : 7
sum : 10
multi : 14
sum : 13
multi : 21
sum : 17
multi : 28
sum : 22
multi : 35
sum : 28
multi : 42
sum : 35
multi : 49
sum : 43
multi : 56
sum : 52
multi : 63
8 sum : 9
multi : 8
sum : 11
multi : 16
sum : 14
multi : 24
sum : 18
multi : 32
sum : 23
multi : 40
sum : 29
multi : 48
sum : 36
multi : 56
sum : 44
multi : 64
sum : 53
multi : 72
9 sum : 10
multi : 9
sum : 12
multi : 18
sum : 15
multi : 27
sum : 19
multi : 36
sum : 24
multi : 45
sum : 30
multi : 54
sum : 37
multi : 63
sum : 45
multi : 72
sum : 54
multi : 81

等価


さて、これからはクエリの練習をやってみます。

multipleの値が24になるものを探すと、
  • 3 x 8 = 24
  • 4 x 6 = 24
  • 6 x 4 = 24
  • 8 x 3 = 24

の4つが該当します。

というわけで、イコールクエリーを発行するわけですが、

これの指定方法は簡単です。

findメソッドの引数にハッシュを渡すだけです。

上記の例では

db.items.find([multiple : 24])

という形で検索することができます。

では、テストをしてみましょう。

MongoTest.groovy

import org.junit.Test
import com.gmongo.GMongo
import org.junit.Before
import com.mongodb.DB
import org.junit.After


    GMongo mongo

    DB db

    static List<Integer> list = [1,2,3,4,5,6,7,8,9]

    static String name = 'name'

    int count = 81

    @Before
    public void setUp() {
        mongo = new GMongo("localhost", 27017)
        db = mongo.getDB("mydb")
        def store = db[items]
        def objects = []
        list.each { x ->
            def base = x
            list.each { y ->
                base += y
                def multiple = x * y
                objects << [
                        name : name,
                        xIndex : x,
                        yIndex : y,
                        sum : base,
                        multiple : multiple]
            }
        }
        objects.each { obj ->
            store.insert(obj)
        }
    }

    @After
    public void tearDown() {
        db.items.remove([:])
    }

    @Test
    public void equalQuery() {
        def result = db.items.find([multiple : 24])
        assert result.size() == 4
        result.each {
            println it
        }
    }



実行結果は次のとおりです。


みごとに予定通り検索できています。

不等号


不等号も、前回と同様に$gte;のような記号をハッシュのキーとして用いることで指定できます。

例えば、xIndexの値が3より小さい場合は$lt;を用いて、

[xIndex : [$lt : 3]]
となります。

では、実際にテストを実施してみます。

このテストでは、xIndexの値が3より小さく、1以上の値を検索しています。

MongoTest.groovy

import org.junit.Test
import com.gmongo.GMongo
import org.junit.Before
import com.mongodb.DB
import org.junit.After

    GMongo mongo

    DB db

    static List<Integer> list = [1,2,3,4,5,6,7,8,9]

    static String name = 'name'

    static String items = 'items'

    int count = 81

    @Before
    public void setUp() {
        mongo = new GMongo("localhost", 27017)
        db = mongo.getDB("mydb")
        def store = db[items]
        def objects = []
        list.each { x ->
            def base = x
            list.each { y ->
                base += y
                def multiple = x * y
                objects << [
                        name : name,
                        xIndex : x,
                        yIndex : y,
                        sum : base,
                        multiple : multiple]
            }
        }
        objects.each { obj ->
            store.insert(obj)
        }
    }

    @After
    public void tearDown() {
        db.items.remove([:])
    }

    @Test
    public void testQuery() {
        def store = db['items']
        def list = store.find([xIndex : [$lt : 3, $gte : 1]])
        assert list.size() == 18
        list.each {
            assert it.xIndex in new IntRange(1,2)
        }
    }



そして、テスト結果は次のような感じです。


GMongoを使うと、かなりmongoを直接扱っている感じがして、非常に融合性が高い気がします。

では、次回はインデックスについて学びたいと思います。

それと、次回のG* Advent Calendar『クソゲーによる自己紹介』で見事Groovy合宿のGDK48で最優秀賞を獲得した@uehajさんです。



0 件のコメント:

コメントを投稿