IBM Cloudant(Apache CouchDB) の MapReduce ビューを使って、特定フィールドの値ごとの文書数を返す API を作ってみました。
なお以下の内容は IBM Cloudant でも Apache CouchDB でも同様に有効だと思っていますが、スクリーンショットなどは IBM Cloudant のものを使って説明しています。ご了承ください。
まず、前提として現状 Cloudant DB 内に以下のような JSON 文書が複数格納されているとします:
"name" フィールドに名前、"date" フィールドに日付文字列が格納されます。同じ "name" の値でも "date" の値は異なっていたり、同じ "date" の値でも "name" は異なっていたりするとします:
この DB の状態から
名前(name)ごとにグルーピングして、文書数がいくつずつあるか?
を調べる、というのが今回やりたいことです。
例えば上記例の場合であれば、"name" = "K.Kimura" の文書数は 5 、"name" = "K.Hashimoto" の文書数は 3 、"name" = "M.Matsuoka" の文書数は 2 、といった結果を導き出すための方法です。SQL の使える RDB であれば count() 関数と group by 句を使えば簡単そうですが、NoSQL 型である Cloudant でいちいち全件検索してから "name" の値ごとにカウントして・・・という REST API を作らずに調べるにはどうすればいいでしょうか?
その答が本ブログエントリのテーマでもある MapReduce ビューを作って、Cloudant REST API でこのビューを呼び出すことで実現できます。以下、その手順を紹介します。
まず DB 内に MapReduce ビューを定義するデザイン文書を作成します。画面左のメニュー "Design Documents" の+部分をクリックし、"New Doc" を選択します:
新規にデザイン文書を追加する編集画面になるので、以下の内容を入力して "Create Document" ボタンをクリックします:
JSON の中身を一応解説すると、"myindex" という名前のデザイン文書を作り、その中で "count_by_name" という名前のビューを定義しています。このビューではまず "name" の値ごとにソート(map)し、その結果を _count 関数でカウント(reduce)した結果を値として持つよう定義しています。
正しく操作できていると Design Documents の中に定義した文書が追加されているはずです。これで MapReduce ビューが定義できました。
後は Cloudant REST API でこのビューを呼ぶだけで結果を得ることができます。IBM Cloudant のホストURL (https://xxxx.cloudant.com)に続けて、DB 名(mapreduce)、デザイン文書名(myindex)とビュー名(count_by_name)を指定し、以下の URL にウェブブラウザでアクセスします:
https://xxxx.cloudant.com/mapreduce/_design/myindex/_view/count_by_name?group=true
すると以下のような結果が得られ、期待通りの結果を参照することができました:
これで「DB 内にどんな名前の文書が存在しているか」や「各名前ごとの文書数」を簡単に調べることができるようになりました。
後はこのような処理を行う必要があるぶんだけビューを追加で定義しておけば、それぞれのビューごとに(フィールドとその値ごとに)文書数を調べたり、特定フィールド値の合計値を求めることができるようになります。
なお以下の内容は IBM Cloudant でも Apache CouchDB でも同様に有効だと思っていますが、スクリーンショットなどは IBM Cloudant のものを使って説明しています。ご了承ください。
まず、前提として現状 Cloudant DB 内に以下のような JSON 文書が複数格納されているとします:
{ "_id": "(id値)", "name": "(名前)", "date": "(日付)" }
"name" フィールドに名前、"date" フィールドに日付文字列が格納されます。同じ "name" の値でも "date" の値は異なっていたり、同じ "date" の値でも "name" は異なっていたりするとします:
この DB の状態から
名前(name)ごとにグルーピングして、文書数がいくつずつあるか?
を調べる、というのが今回やりたいことです。
例えば上記例の場合であれば、"name" = "K.Kimura" の文書数は 5 、"name" = "K.Hashimoto" の文書数は 3 、"name" = "M.Matsuoka" の文書数は 2 、といった結果を導き出すための方法です。SQL の使える RDB であれば count() 関数と group by 句を使えば簡単そうですが、NoSQL 型である Cloudant でいちいち全件検索してから "name" の値ごとにカウントして・・・という REST API を作らずに調べるにはどうすればいいでしょうか?
その答が本ブログエントリのテーマでもある MapReduce ビューを作って、Cloudant REST API でこのビューを呼び出すことで実現できます。以下、その手順を紹介します。
まず DB 内に MapReduce ビューを定義するデザイン文書を作成します。画面左のメニュー "Design Documents" の+部分をクリックし、"New Doc" を選択します:
新規にデザイン文書を追加する編集画面になるので、以下の内容を入力して "Create Document" ボタンをクリックします:
{ "_id": "_design/myindex", "language": "query", "views": { "count_by_name": { "map": { "fields": { "name": "asc" }, "partial_filter_selector": {} }, "reduce": "_count", "options": { "def": { "fields": [ "name" ] } } } } }
JSON の中身を一応解説すると、"myindex" という名前のデザイン文書を作り、その中で "count_by_name" という名前のビューを定義しています。このビューではまず "name" の値ごとにソート(map)し、その結果を _count 関数でカウント(reduce)した結果を値として持つよう定義しています。
正しく操作できていると Design Documents の中に定義した文書が追加されているはずです。これで MapReduce ビューが定義できました。
後は Cloudant REST API でこのビューを呼ぶだけで結果を得ることができます。IBM Cloudant のホストURL (https://xxxx.cloudant.com)に続けて、DB 名(mapreduce)、デザイン文書名(myindex)とビュー名(count_by_name)を指定し、以下の URL にウェブブラウザでアクセスします:
https://xxxx.cloudant.com/mapreduce/_design/myindex/_view/count_by_name?group=true
すると以下のような結果が得られ、期待通りの結果を参照することができました:
{ "rows": [ { "key" : [ "K.Hashimoto" ], "value" : 3 }, { "key" : [ "K.Kimura" ], "value" : 5 }, { "key" : [ "M.Matsuoka" ], "value" : 2 } ] }
これで「DB 内にどんな名前の文書が存在しているか」や「各名前ごとの文書数」を簡単に調べることができるようになりました。
後はこのような処理を行う必要があるぶんだけビューを追加で定義しておけば、それぞれのビューごとに(フィールドとその値ごとに)文書数を調べたり、特定フィールド値の合計値を求めることができるようになります。