Born Too Late

Yuya's old tech blog.

MongoDB の MapReduce を Ruby の DSL で定義するフレームワーク Mr. Mongo 作った

2013-04-08 03:00:35

500 円玉貯金が N 万円貯まったので Thunderbolt Display を購入しました。
現在の開発環境の様子です。
画面が広いと Vim で複数ファイル広げたり、ファイル更新時にはその横でユニットテストが自動実行されたり、別のペインで tig や htop を実行しておくこともできるので便利ですね。
あとは最近少女革命ウテナ DVD-BOX を買ったんですが、これも大画面で観られるようになりました。

そんな大画面でつくった gem を紹介します。

Mr. Mongo とは

yuya-takeyama/mr_mongo

MongoDB の MapReduce の定義を Ruby の内部 DSL で記述し、実行するためのフレームワークです。
Ruby で、といっても map/reduce の関数は JavaScript です。

例えばワードカウントであれば、以下のような記述になります。

map/reduce を __END__ 以降に記述できるのが特徴です。
ここでは使われていませんが、finalize も同様に定義できます。

なお、__END__ 以降の読み込みについては先日開発した InlineTemplateLoader を使用しています。

何で DSL が必要か

ひとつは書き方・定義の仕方を統一するため、もうひとつはユニットテストのためです。

書き方を統一する

MongoDB 標準のやり方にしろ、各言語向けのドライバを使うにしろ、そのままだと人によって書き方がいろいろ異なります。
そこにこの Mr. Mongo を導入することで、「1 ファイル 1 ジョブ」というルールが強制されるようになります。

MapReduce をユニットテストするということ

MongoDB における MapReduce のユニットテストについては、ほとんど言及されることが無いと思いますが、やはり重要なんじゃないかと考えています。
上記のような単純なワードカウント程度の例ならともかく、大量のデータを、複雑に処理し、しかも長期的にメンテナンスを行うのであれば、回帰テストとしてのユニットテストが無くては安心できません。

また、テスト駆動で開発することでより効率よく開発できるケースもあるでしょう。

Mr. Mongo でどうユニットテストを書くか

これについては現状でもできなくはないのですが、フレームワークとしてのサポートがまだ貧弱な状態です。
mr_mongo-rspec-matcher なんてのを作って RSpec でのユニットテストをやりやすくする、というアイディアはあるものの、まだ実装できていません。

一応現在のコードベースでも MapReduce のユニットテストはできています
MapReduce をオンメモリで実行し、その結果を連想配列と比較しています。

これをもっとフレームワークっぽいやり方でできるようになれば、いろいろ捗るんじゃないかと思っています。

あと、以前作った mongo_require.js を併用することで、MapReduce ジョブをある程度モジュール化して記述すれば、これもまたメンテナビリティに寄与すると思われます。

まとめ

MongoDB の MapReduce を効率よく開発・管理するためのフレームワーク Mr. Mongo について紹介しました。

おやすみなさい。