2014年12月31日水曜日

CouchDBをMapReduceで処理してみる

さてせっかくなので、MapReduce機能を使ってCouchDBのデータ処理をメモしておきます。
調べているうちに非常にわかりやすい所があり、MapReduceの説明にもちょうどよかったので自分なりに解釈して記しておきます。

まずデータを用意しないといけません。以下のような家計簿もどきを用意します。

date    category      item       price
5/10     果物           バナナ       300
5/10       魚               鯛         1000
5/11     果物           みかん       300
5/11     果物           バナナ       300
5/12       魚               鯛           900

各行が1個のドキュメントにあたります。(とりあえず全ドキュメントが持つFieldは同じにしておきます。その方が説明が楽なので。)

FutonでViewをTemplateに切り替えます。するとMapとReduceのプログラムを入力する欄が表示されます。そこでMapとして以下を入力します。

function(doc) {
  emit(null, doc.price);
}

すると全ドキュメントから価格だけ抜き出して一覧表示してくれます。


Reduceのプログラムをしてないので、データの抜き出しだけした結果です。
後、if文で特定のFieldのドキュメントだけ抜き出すこともできます。


次にReduce欄に以下を入力します。Reduce処理として集めたデータの加算を指示しています。

function(keys, values) {
  return sum(values);
}

すると以下の様になります。(emitの第1引数がkeysになり、第2引数がvaluesになるという関係です)


って言いたいところですが、Reduceが動いていない... よく見たらviewの右上にReduceにチェックを入れるボタンが。


どうもここにチェックを入れないとReduce処理をしてくれないようです。無事合計がでてくれました。

次に日付毎の価格を集計してみます。Map欄に以下を入力します。

function(doc) {
  emit(doc.date, doc.price);
}

key欄にdateを指定し、それ毎の塊を作ります。その時、priceの値だけを集めてきます。それをReduceで集計すれば日付ごとの価格の集計になります。


次にcategory毎の件数を集計してみます。とりあえずkeyにcategoryを指定すれば、category毎の塊は作成してくれます。

function(doc) {
  emit(doc.category, 1);
}

この時、valuesに「1」を固定して指定します。つまり集めた塊ごとに「1」の値が与えられることになります。これを集計すれば塊の件数になります。Reduce欄には例によってvaluesの集計をするようにします。


ということで、categoryの件数が出力されました。

本来、MapReduceはGoogleが考えだしたみたいに多数の計算機で処理するのが本当で、1台のPCでやっても旨味があまりありませんが、非常にわかりやすくドキュメント型のデータを処理してくれます。
後はこのMap欄やReduce欄のコードをアプリ側から自由に実行できないと、CouchDBの本当のいいところがでてこないでしょうが、それはまたメモできる程度、試行できたら。(Map欄のコードを実行した例は2回前のCouchDBのメモでもう記してますから、わかりやすいデータが思いつけば書けるでしょう)

0 件のコメント:

コメントを投稿