# groonga - オープンソースのカラムストア機能付き全文検索エンジン

- English

# 4.5. ドリルダウン

これまでのセクションで検索方法と検索結果をどのようにソートするかを学びました。思うがままに検索できるようになりましたね。それでは、次のことをするにはどうすればよいでしょか。まず、あるカラムに注目します。そして、そのカラムの値が同じレコードを集め、それぞれの値毎に集まったレコードの数を数えます。

素朴な実現方法は、カラムのそれぞれの値で検索する方法です。結果として、すべてのカラムの値についてレコード数を求めることができます。シンプルな方法ですが、たくさんのレコードがある場合には現実的ではありません。

SQLに慣れている人は、「GroongaにはSQLでいう `GROUP BY` 相当の機能はないの？」と思うでしょう。

もちろん、Groongaはそのような機能を提供しています。それが `drilldown` と呼んでいる機能です。

`drilldown` はカラムの値ごとにレコード数を数える機能を提供します。値ごとに別々のクエリーになるのではなく、1回のクエリーですべての値に対してレコード数を数えます。

この機能を説明するために次のケースを考えます。ドメインで分類し、ドメインが属している国ごとにグループ化する、というケースです。

この機能を使った具体的な例を示します。

この例では、 `Site` テーブルに2つのカラムを追加しています。 `domain` カラムはTLD(トップレベルドメイン)に使います。 `country` カラムは国名に使います。これらのカラムの型はドメイン名を主キーとする `SiteDomain` テーブルと国名を主キーとする `SiteCountry` テーブルです。

実行例:

    table_create --name SiteDomain --flags TABLE_HASH_KEY --key_type ShortText
    # [[0, 1337566253.89858, 0.000355720520019531], true]
    table_create --name SiteCountry --flags TABLE_HASH_KEY --key_type ShortText
    # [[0, 1337566253.89858, 0.000355720520019531], true]
    column_create --table Site --name domain --flags COLUMN_SCALAR --type SiteDomain
    # [[0, 1337566253.89858, 0.000355720520019531], true]
    column_create --table Site --name country --flags COLUMN_SCALAR --type SiteCountry
    # [[0, 1337566253.89858, 0.000355720520019531], true]
    load --table Site
    [
    {"_key":"http://example.org/","domain":".org","country":"japan"},
    {"_key":"http://example.net/","domain":".net","country":"brazil"},
    {"_key":"http://example.com/","domain":".com","country":"japan"},
    {"_key":"http://example.net/afr","domain":".net","country":"usa"},
    {"_key":"http://example.org/aba","domain":".org","country":"korea"},
    {"_key":"http://example.com/rab","domain":".com","country":"china"},
    {"_key":"http://example.net/atv","domain":".net","country":"china"},
    {"_key":"http://example.org/gat","domain":".org","country":"usa"},
    {"_key":"http://example.com/vdw","domain":".com","country":"japan"}
    ]
    # [[0, 1337566253.89858, 0.000355720520019531], 9]

`domain` カラムでドリルダウンする例を示します。 3つの値が `domain` カラムでは使われています。".org"、".net"そして".com"です。

実行例:

    select --table Site --limit 0 --drilldown domain
    # [
    #   [
    #     0,
    #     1337566253.89858,
    #     0.000355720520019531
    #   ],
    #   [
    #     [
    #       [
    #         9
    #       ],
    #       [
    #         [
    #           "_id",
    #           "UInt32"
    #         ],
    #         [
    #           "_key",
    #           "ShortText"
    #         ],
    #         [
    #           "country",
    #           "SiteCountry"
    #         ],
    #         [
    #           "domain",
    #           "SiteDomain"
    #         ],
    #         [
    #           "link",
    #           "Site"
    #         ],
    #         [
    #           "links",
    #           "Site"
    #         ],
    #         [
    #           "location",
    #           "WGS84GeoPoint"
    #         ],
    #         [
    #           "title",
    #           "ShortText"
    #         ]
    #       ]
    #     ],
    #     [
    #       [
    #         3
    #       ],
    #       [
    #         [
    #           "_key",
    #           "ShortText"
    #         ],
    #         [
    #           "_nsubrecs",
    #           "Int32"
    #         ]
    #       ],
    #       [
    #         ".org",
    #         3
    #       ],
    #       [
    #         ".net",
    #         3
    #       ],
    #       [
    #         ".com",
    #         3
    #       ]
    #     ]
    #   ]
    # ]

上記のクエリの集計結果です。

`domain` カラムによるドリルダウン
グループ化するカラムの値 | グループ化されたレコード数 | グループ化されたレコードは次のとおり
--- | --- | ---
.org | 3 | http://example.org/ http://example.org/aba http://example.org/gat
.net | 3 | http://example.net/ http://example.net/afr http://example.net/atv
.com | 3 | http://example.com/ http://example.com/rab http://example.com/vdw

ドリルダウン結果は `_nsubrecs` カラムの値として返ります。この場合は、`Site` テーブルは ".org"、".net"、".com"ドメインでグループ化されています。 `_nsubrecs` はグループ化されたドメインが3つのレコードをそれぞれもつことを意味します。

テーブル型を持つカラムに対してドリルダウンを行った場合、参照先のテーブルに存在するカラム値を取得することもできます。ドリルダウンを行ったテーブルには、 `_nsubrecs` という仮想的なカラムが追加されます。このカラムには、グループ化されたレコード数が入ります。

では、参照されているテーブルの詳細を調べてみましょう。 `Site` テーブルは `SiteDomain` テーブルを `domain` カラムの型として使っています。 `--drilldown_output_columns` を参照されているカラムの詳細を知るのに使えます。

実行例:

    select --table Site --limit 0 --drilldown domain --drilldown_output_columns _id,_key,_nsubrecs
    # [
    #   [
    #     0,
    #     1337566253.89858,
    #     0.000355720520019531
    #   ],
    #   [
    #     [
    #       [
    #         9
    #       ],
    #       [
    #         [
    #           "_id",
    #           "UInt32"
    #         ],
    #         [
    #           "_key",
    #           "ShortText"
    #         ],
    #         [
    #           "country",
    #           "SiteCountry"
    #         ],
    #         [
    #           "domain",
    #           "SiteDomain"
    #         ],
    #         [
    #           "link",
    #           "Site"
    #         ],
    #         [
    #           "links",
    #           "Site"
    #         ],
    #         [
    #           "location",
    #           "WGS84GeoPoint"
    #         ],
    #         [
    #           "title",
    #           "ShortText"
    #         ]
    #       ]
    #     ],
    #     [
    #       [
    #         3
    #       ],
    #       [
    #         [
    #           "_id",
    #           "UInt32"
    #         ],
    #         [
    #           "_key",
    #           "ShortText"
    #         ],
    #         [
    #           "_nsubrecs",
    #           "Int32"
    #         ]
    #       ],
    #       [
    #         1,
    #         ".org",
    #         3
    #       ],
    #       [
    #         2,
    #         ".net",
    #         3
    #       ],
    #       [
    #         3,
    #         ".com",
    #         3
    #       ]
    #     ]
    #   ]
    # ]

これでグループ化されたドメインの詳細がわかります。 `domain` の値が".org"であるレコードに対して `country` カラムを使ってドリルダウンしてみましょう。

実行例:

    select --table Site --limit 0 --filter "domain._id == 1" --drilldown country
    # [
    #   [
    #     0,
    #     1337566253.89858,
    #     0.000355720520019531
    #   ],
    #   [
    #     [
    #       [
    #         3
    #       ],
    #       [
    #         [
    #           "_id",
    #           "UInt32"
    #         ],
    #         [
    #           "_key",
    #           "ShortText"
    #         ],
    #         [
    #           "country",
    #           "SiteCountry"
    #         ],
    #         [
    #           "domain",
    #           "SiteDomain"
    #         ],
    #         [
    #           "link",
    #           "Site"
    #         ],
    #         [
    #           "links",
    #           "Site"
    #         ],
    #         [
    #           "location",
    #           "WGS84GeoPoint"
    #         ],
    #         [
    #           "title",
    #           "ShortText"
    #         ]
    #       ]
    #     ],
    #     [
    #       [
    #         3
    #       ],
    #       [
    #         [
    #           "_key",
    #           "ShortText"
    #         ],
    #         [
    #           "_nsubrecs",
    #           "Int32"
    #         ]
    #       ],
    #       [
    #         "japan",
    #         1
    #       ],
    #       [
    #         "korea",
    #         1
    #       ],
    #       [
    #         "usa",
    #         1
    #       ]
    #     ]
    #   ]
    # ]

## 4.5.1. 複数のカラムでドリルダウン

ドリルダウンでは複数のカラムをサポートしています。 `drilldown` パラメータの引数にカンマ区切りの値を指定します。すると一度にまとめてドリルダウン結果を取得できます。

実行例:

    select --table Site --limit 0 --drilldown domain,country
    # [
    #   [
    #     0,
    #     1337566253.89858,
    #     0.000355720520019531
    #   ],
    #   [
    #     [
    #       [
    #         9
    #       ],
    #       [
    #         [
    #           "_id",
    #           "UInt32"
    #         ],
    #         [
    #           "_key",
    #           "ShortText"
    #         ],
    #         [
    #           "country",
    #           "SiteCountry"
    #         ],
    #         [
    #           "domain",
    #           "SiteDomain"
    #         ],
    #         [
    #           "link",
    #           "Site"
    #         ],
    #         [
    #           "links",
    #           "Site"
    #         ],
    #         [
    #           "location",
    #           "WGS84GeoPoint"
    #         ],
    #         [
    #           "title",
    #           "ShortText"
    #         ]
    #       ]
    #     ],
    #     [
    #       [
    #         3
    #       ],
    #       [
    #         [
    #           "_key",
    #           "ShortText"
    #         ],
    #         [
    #           "_nsubrecs",
    #           "Int32"
    #         ]
    #       ],
    #       [
    #         ".org",
    #         3
    #       ],
    #       [
    #         ".net",
    #         3
    #       ],
    #       [
    #         ".com",
    #         3
    #       ]
    #     ],
    #     [
    #       [
    #         5
    #       ],
    #       [
    #         [
    #           "_key",
    #           "ShortText"
    #         ],
    #         [
    #           "_nsubrecs",
    #           "Int32"
    #         ]
    #       ],
    #       [
    #         "japan",
    #         3
    #       ],
    #       [
    #         "brazil",
    #         1
    #       ],
    #       [
    #         "usa",
    #         2
    #       ],
    #       [
    #         "korea",
    #         1
    #       ],
    #       [
    #         "china",
    #         2
    #       ]
    #     ]
    #   ]
    # ]

## 4.5.2. ドリルダウン結果をソートする

ドリルダウン結果をソートしたい場合には `--drilldown_sortby` を使います。指定した `_nsubrecs` カラムを昇順でソートします。

実行例:

    select --table Site --limit 0 --drilldown country --drilldown_sortby _nsubrecs
    # [
    #   [
    #     0,
    #     1337566253.89858,
    #     0.000355720520019531
    #   ],
    #   [
    #     [
    #       [
    #         9
    #       ],
    #       [
    #         [
    #           "_id",
    #           "UInt32"
    #         ],
    #         [
    #           "_key",
    #           "ShortText"
    #         ],
    #         [
    #           "country",
    #           "SiteCountry"
    #         ],
    #         [
    #           "domain",
    #           "SiteDomain"
    #         ],
    #         [
    #           "link",
    #           "Site"
    #         ],
    #         [
    #           "links",
    #           "Site"
    #         ],
    #         [
    #           "location",
    #           "WGS84GeoPoint"
    #         ],
    #         [
    #           "title",
    #           "ShortText"
    #         ]
    #       ]
    #     ],
    #     [
    #       [
    #         5
    #       ],
    #       [
    #         [
    #           "_key",
    #           "ShortText"
    #         ],
    #         [
    #           "_nsubrecs",
    #           "Int32"
    #         ]
    #       ],
    #       [
    #         "brazil",
    #         1
    #       ],
    #       [
    #         "korea",
    #         1
    #       ],
    #       [
    #         "usa",
    #         2
    #       ],
    #       [
    #         "china",
    #         2
    #       ],
    #       [
    #         "japan",
    #         3
    #       ]
    #     ]
    #   ]
    # ]

## 4.5.3. ドリルダウン結果の制限

ドリルダウン結果はデフォルト10件に制限されています。 `drilldown_limit` と `drilldown_offset` パラメータをドリルダウン結果をカスタマイズするのに使います。

実行例:

    select --table Site --limit 0 --drilldown country --drilldown_sortby _nsubrecs --drilldown_limit 2 --drilldown_offset 2
    # [
    #   [
    #     0,
    #     1337566253.89858,
    #     0.000355720520019531
    #   ],
    #   [
    #     [
    #       [
    #         9
    #       ],
    #       [
    #         [
    #           "_id",
    #           "UInt32"
    #         ],
    #         [
    #           "_key",
    #           "ShortText"
    #         ],
    #         [
    #           "country",
    #           "SiteCountry"
    #         ],
    #         [
    #           "domain",
    #           "SiteDomain"
    #         ],
    #         [
    #           "link",
    #           "Site"
    #         ],
    #         [
    #           "links",
    #           "Site"
    #         ],
    #         [
    #           "location",
    #           "WGS84GeoPoint"
    #         ],
    #         [
    #           "title",
    #           "ShortText"
    #         ]
    #       ]
    #     ],
    #     [
    #       [
    #         5
    #       ],
    #       [
    #         [
    #           "_key",
    #           "ShortText"
    #         ],
    #         [
    #           "_nsubrecs",
    #           "Int32"
    #         ]
    #       ],
    #       [
    #         "usa",
    #         2
    #       ],
    #       [
    #         "china",
    #         2
    #       ]
    #     ]
    #   ]
    # ]

文字列を格納しているカラムのドリルダウンは、他の型のカラムのドリルダウンよりも遅くなることに注意してください。文字列型のカラムでドリルダウンするときは、主キーの方が文字列のテーブルを作って、そのテーブルを参照するカラムにしてください。