Mongoidによるatomicな更新
MongoDBの特徴として、RDBMSではおおよそ用いられる以下の方法が使えない。
- joinがない
- transactionがない
そのかわり、次の特徴がある
- 埋め込みドキュメントが使える
- ドキュメントの各要素について、atomicな更新ができる
前者は例えば「紐付けて必ず参照するドキュメント」を内包させておくことで、一度のクエリで紐付く情報を一括取得できる。
後者は行ロックしてupdate(ロジック的には行ロック、データコピー、要素の更新、DB上書きの順になるのかな)などを行わず、各要素を上書きしてしまう方法である。
これらについて困っていたことがあって、まず、あるドキュメントの普通の要素を上書きする場合は以下で可能だった。
@parent = Parent.all.first # 既存ドキュメントの取り出し。 puts @parent.name #=> hogehoge @parent.update_attributes({ :name => "fugafuga" }) puts @parent.name #=> fugafuga Parent.all.first.name #=> fugafuga # @parent.save してないが上書きされる
一方で、埋め込みドキュメントに対する push (1要素追加するatomicな操作)がわからなかったのだが、公式ドキュメントの最後にちらっと出てくる方法で次のように解決した。
@parent = Parent.all.first # 既存ドキュメントの取り出し。 p @parent.children.size #=> 1 @parent.children.create({ :name => "fuga-chan" }) p @parent.children.size #=> 2 Parent.all.first.children.size #=> 2 # @parent.save してないがDB上も挿入されている
まだpullとか判っていない部分もあるが、とりあえずatomicな操作が可能であることが分かってよかった。