2012年6月20日水曜日

mongoDB、MapReduceでカレンダー


コレクションを、指定された期間で日付をキーにMapReduceした帳票を出力する、
って割とありふれたニーズだと思います。例えばこんなコレクションがあって、

<TODO>
contentdoneinsert
hoge2012/06/192012/06/17
piyo2012/06/19
foo2012/06/212012/06/19

以下のようなある週の日毎のTodo消化数一覧を表示したいとか。

  {"_id"=>2012-06-16 15:00:00 UTC, "value"=>{"done_count"=>0}}
  {"_id"=>2012-06-17 15:00:00 UTC, "value"=>{"done_count"=>0}}
  {"_id"=>2012-06-18 15:00:00 UTC, "value"=>{"done_count"=>1.0}}
  {"_id"=>2012-06-19 15:00:00 UTC, "value"=>{"done_count"=>0}}
  {"_id"=>2012-06-20 15:00:00 UTC, "value"=>{"done_count"=>1.0}}
  {"_id"=>2012-06-21 15:00:00 UTC, "value"=>{"done_count"=>0}}
  {"_id"=>2012-06-22 15:00:00 UTC, "value"=>{"done_count"=>0}}

PostgreSQLならgenerate_seriesで日付のテーブルを作ってこれに結合すれば期待する結果が得られると思います、mongoでも同様のことがしたくて試行錯誤してみました、
rubyでの実装です、

至極単純で、map関数でemitされるのと同様の形式でカレンダーコレクションを前もって作っておいて、これにMapReduceの結果をmergeするだけです。
カレンダーコレクション―MapReduceの出力先はランダム文字列と共に生成、使用後はdropして、衝突しないようにしています。
* moment.jsインクルードしていますが、実はこのpullリクエスト通らないと動きません、
 

結局これって、一時的なコレクション作ってそれにjoinしてるわけで、カレンダーに限らずSQLのwith句駆使して実装してる処理とかも(泥臭く、且つ分かり易く)実装できそう。

0 件のコメント:

コメントを投稿