CouchDB徒然
http://blog.livedoor.jp/habuakihiro/archives/65219163.html
羽生さんのERDレッスンとかSQLドリルなどにはかなりお世話になったので、ものすごく興味深く拝読させていただいた。
物心ついたとき?にはRDBMSが当たり前?になっていた時代*1に生まれたこともあっていろいろと思うところがある、ので感想を書き留めておきたい。
これの何が不便かというと、最初に上限を10とかにしてて、たまたまある売上の明細が11件になってしまった場合に格納できないということになるのです。
これは、Excel で売り上げ管理用のフォーム付きシートを作ってみたものの、Excelの表は固定幅なので自由がきかず、Accessを買ってみた、という感覚でしょうか。Access を RDBMS というと怒られるんだけれども、Excel よりはリレーションの概念に近づけるか、みたいな。
例えば売上データに対して商品マスタや顧客マスタのようなものとのリレーションシップというのは、COBOLの頃からも普通に別ファイルとして切り出していましたし、ライフサイクルが違うので分かれていることに対して違和感がないのです。一方で、明細というのは、所謂見出し部分とライフサイクルが(基本的には)一致している(そうでないこともあるのだけど)ので、扱いが面倒に感じられてしまうのです。
これをよんだときに、今の自分のCouchDBのデータ定義が、まさにこれ。マスター系には hogehoge_id で参照を定義するけれど、ビジネストランザクション用のデータは配列に放り込んでいる。並び替えとか、グループ化したいのであれば、MapReduceのMapフェーズでばらせばいいじゃん、という話で。
「たまたまこういう書式の伝票があるから使ってるだけ」というのが実際のところだと思うのです。要するに「人が手作業をしやすいように発展した書式を電子化してる」ということです。人はそれほど高尚ではないし、また高尚であるから素晴らしいというものでもないのです。
問題は人は高尚ではない、ということですよね。オブジェクト指向の初期の頃(もうさすがにこんな教育はしていないと思いたいけれど)、「ほ乳類、という抽象クラスがあって、それを継承した猫というクラスがいます、犬というクラスがいます」という説明をしている人を見つけては「ほ乳類というのは、猫や犬などの実装を詳しく調べていった結果、その場で都合のよい形で定義された概念であって、最初から決めておくのは無理だと思うんですけれど」といって困らせてしまった記憶があります。
そういう意味だと、RDBの「正規化」という作業は非常にわかりやすかった反面、正規化した結果しか知らないのでは、この各表がどんなビジネス上の意味を持つのかわからないんじゃないかなぁ、と思ったりも。まぁコンピューターは知る必要がないので、正規化する前のモデルをドキュメントとして残しておけばいいんでしょうけど、実際残っているケースに出くわしたのはまれで、正規化された表スキーマから、おそらくこんな業務をやっているんだ、という想像を働かせながらアプリケーションを書いたことの方が多かったですけど。
スキーマレスでありながら_typeを強要するようではちょっとねぇという気分になるのは自然なことでしょう。
...
, "type": "売上伝票"
一方で、id:yohei さんは、
CouchRestも勝手に作るけどtypeはいらない気がするんだよなあ。期待した構造のdetailsというプロパティがあったら、よしなに処理しちゃう方が、たぶん僕が想定しているアプリには合うんだろうな。
これは個人的には、両方のケースですかね。ある程度DBに渡されるデータに想定があるとなると、プログラムを簡潔に書くために、type という名前の属性をつけたくなる。一方で、何でもイイからこの属性名を持つデータを片っ端から処理したい、という場合にはtypeというのはいらなくなる。
この辺はアプリケーション次第で、あるドメインに特化した処理を実装するアプリは(羽生さんがかかれている帳票処理など)typeがあることを期待し、一方でドメインをまたがって処理するようなアプリケーション(検索とか機械学習エンジンなど)は、typeなんていらない、という形になるのではないかと思います。
羽生さんの例でちょっとよくわからなかったのは、伝票番号はnumberでかかれていたけれど、quantity, amount などがstringになっていた点。typo?と思ったんだけれども、その後のMap関数でparseIntをしている以上は何か意図があってのことかと思っていて、すごく気になるところです。
CouchDBに関するドキュメントでスキーマレスならぬ「スキーマフリー」という言葉が良く使われているのですが、正に自由なスキーマのメリットは非常に大きなものだと感じます
個人的には semi-structured data と呼ぶのが気に入っています。先述のtypeなどのように、データモデルとしてある程度はアプリケーションドメイン共通の決めごと(structured)とはしつつも、それ以外は勝手に定義(unstructured)していいよ!という意味で。
ちなみに、今はがんばってCouchDBのようなところでのお仕事ができるように*2、いろいろ仕込みをいれているんですけど*3、分野は違えど、だいぶ同じことを考えているなぁーと、今日会社の人たちと飲みながら盛り上がってきた帰り。GW中に書いたコードと動くデモはみせてきて、だからこれDOAでしょ*4!っていってきた。
で、はてブにもViewに対するViewについて、少し書いたけれど、ふと電車の中で、
Client --PUT/POST--> CouchDB -- (ViewsOnUpdate) -- (POST /{db}/_bulk_docs) --> CouchDB --> ... -> CouchDB <-- (GET) Client
って具合に、ViewsOnUpdate機能でMapReduceを適宜再計算しながら、その結果_bulk_docs APIでをパイプのごとくつないでいけば、 Viewに対するViewの機能は実現できるんじゃないかなぁ、と思った。これなんていう、RelaxDFDっていう話はあるんですが、これはあとで試してみようか(その前に記事のほう優先しますが)。