MongoDB アトミック操作

MongoDBはトランザクションをサポートしていません。そのため、プロジェクトで適用する際にはこの点に注意してください。どのような設計でも、MongoDBにデータの整合性を保証することを要求しないでください。

しかし、MongoDBには多くのアトミック操作が用意されています。例えば、ドキュメントの保存、変更、削除などはすべてアトミック操作です。

アトミック操作とは、このドキュメントがMongoDBに保存されるか、MongoDBに保存されないかのどちらかであり、クエリで取得したドキュメントが完全に保存されていないという状況は発生しません。


アトミック操作データモデル

次の例を考えてみましょう。図書館の書籍と貸出情報です。

この例は、同じドキュメント内で、埋め込みフィールドがアトミック操作(update:更新)に関連するフィールドと同期していることを確認する方法を示しています。

book = {
          _id: 123456789,
          title: "MongoDB: The Definitive Guide",
          author: [ "Kristina Chodorow", "Mike Dirolf" ],
          published_date: ISODate("2010-09-24"),
          pages: 216,
          language: "English",
          publisher_id: "oreilly",
          available: 3,
          checkout: [ { by: "joe", date: ISODate("2012-10-15") } ]
        }

db.collection.findAndModify() メソッドを使用して、書籍が貸出可能かどうかを判断し、新しい貸出情報を更新できます。

同じドキュメントに埋め込まれた available フィールドと checkout フィールドにより、これらのフィールドが同期して更新されることを確認します:

db.books.findAndModify ( {
   query: {
            _id: 123456789,
            available: { $gt: 0 }
          },
   update: {
             $inc: { available: -1 },
             $push: { checkout: { by: "abc", date: new Date() } }
           }
} )

アトミック操作のよく使うコマンド

$set

キーを指定してキー値を更新するために使用します。キーが存在しない場合は作成します。

{ $set : { field : value } }

$unset

キーを削除するために使用します。

{ $unset : { field : 1} }

$inc

$inc は、ドキュメント内の値が数値型(要件を満たす数値のみ)であるキーに対して増減の操作を行うことができます。

{ $inc : { field : value } }

$push

使い方:

{ $push : { field : value } }

value を field に追加します。field は必ず配列型でなければなりません。field が存在しない場合は、新しい配列型として追加されます。

$pushAll

$push と同じですが、一度に複数の値を配列フィールドに追加できます。

{ $pushAll : { field : value_array } }

$pull

配列 field から value と等しい値を削除します。

{ $pull : { field : _value } }

$addToSet

配列に値を追加しますが、この値が配列内にない場合にのみ追加します。

$pop

配列の最初または最後の要素を削除します。

{ $pop : { field : 1 } }

$rename

フィールド名を変更します。

{ $rename : { old_field_name : new_field_name } }

$bit

ビット演算、integer 型

{$bit : { field : {and : 5}}}

位置演算子

> t.find() { "_id" : ObjectId("4b97e62bf1d8c7152c9ccb74"), "title" : "ABC", "comments" : [ { "by" : "joe", "votes" : 3 }, { "by" : "jane", "votes" : 7 } ] }
 
> t.update( {'comments.by':'joe'}, {$inc:{'comments.$.votes':1}}, false, true )
 
> t.find() { "_id" : ObjectId("4b97e62bf1d8c7152c9ccb74"), "title" : "ABC", "comments" : [ { "by" : "joe", "votes" : 4 }, { "by" : "jane", "votes" : 7 } ] }
その他の拡張