アップデート

Based on v52

MongoDBは、ドキュメント全体を入れ替える通常のアップデートと、アトミックでin-place(その場で)のアップデートをサポートします。

アップデート

これがMongoDBの update() のシンタックスです。

db.collection.update( criteria, objNew, upsert, multi )

引数:

  • criteria - アップデートするレコードを選択するためのクエリー
  • objNew - 対象のオブジェクトを、アップデートするオブジェクト、または $オペレータ($incなど)
  • upsert - レコードが存在しない場合にインサートするかどうか
  • multi - criteria にマッチするオブジェクトすべてをアップデートするかどうか (デフォルトでは最初に見つかったオブジェクトのみがアップデートされる)

mongoシェルで、 save()

mongoシェル 上のsave()コマンドは、一つのオブジェクトをupsertするための簡単なシンタックスです。

// x はJSONスタイルのオブジェクト
db.mycollection.save(x); // 存在していたら update、 してなかったらinsert

save() は、x が _id フィールドを持っていたら、upsert をし、持っていなければ、 insert をします。そのため、通常、upsertを明示的にリクエストする必要なはく、単に save() を使ってください。

upsert は、 "存在していたら update。していなかったら、 insert" という意味です。

myColl.update( { name: "Joe" }, { name: "Joe", age: 20 }, true ); 

modifier オペレーション

modifier オペレーションは、既存の値をアップデートをとても効率的に行います。たとえば、数値のインクリメントなどに向いています。

通常の方法だと、このようになります。

var j=myColl.findOne( { name: "Joe" } ); 
j.n++; 
myColl.save(j); 

modifierアップデートは、クエリーをしオブジェクトを返す、という部分の遅延を省くことができることが利点です。また、modifierアップデートは、 アトミックな オペレーションで、ネットワーク帯域も少ししか使いません。

このアトミックなアップデートを実行するためには、専用のアップデートオペレータのどれか(必ず'$'で始まります)を指定します。

db.people.update( { name:"Joe" }, { $inc: { n : 1 } } );

この例は、「'name'が'Joe'の最初のドキュメントを探し、'n'をインクリメントしろ」ということになります。

この例ではありませんが、ほとんどのmodifierオペレータで、複数のfield/valueのペアを使うことができます。たとえば、次の操作は、xを1に、yを2にセットします。

{ $set : { x : 1 , y : 2 } }

$inc

{ $inc : { field : value } }

field が存在している場合、 fieldvalue インクリメントします。存在しない場合、 fieldvalue をセットします。

$set

{ $set : { field : value } }

fieldvalue をセットします。 すべてのデータタイプが $set ではサポートされています。

$unset

{ $unset : { field : 1} }

fieldを削除します。 v1.3以上の機能です。

$push

{ $push : { field : value } }

field がarrayの場合、 valuefield に追加します。 field が存在しない場合、 field に [value] をセットします。 field は存在するが、arrayではない場合、 errorが発生します。

$pushAll

{ $pushAll : { field : value_array } }

field が存在するarrayの場合、 value_array を一つずつ、 field に追加します。 field が存在しない場合、 field に、 array value_array をセットします。 field は存在するが、arrayではない場合、 errorが発生します。

$addToSet

{ $addToSet : { field : value } }

指定したarrayにvalueが存在していない場合、そのarrayに追加します。

複数の値を追加。

{ $addToSet : { a : { $each : [ 3 , 5 , 6 ] } } }

$pop

{ $pop : { field : 1 } }

arrayの最後の要素を削除します(バージョン1.1で追加)。

{ $pop : { field : -1 } }

arrayの最初の要素を削除します(バージョン1.1で追加)。

$pull

{ $pull : { field : _value } }

field がarrayの場合、すべての valuefield から削除します。 field が存在しているが、arrayではない場合、エラーになります。

$pullAll

{ $pullAll : { field : value_array } }

field がarrayの場合、 value_array の中の値をそれぞれ field からすべて削除します。 field が存在しているが、arrayではない場合、エラーになります。

$ ポジションオペレータ

バージョン 1.3.4 以上

$ オペレータは(それ自身で)、 "クエリでマッチしたアイテムの配列の場所" を意味します。 配列のメンバを探し、それを操作する場合に使えます。 たとえば、
The $ operator (by itself) means "position of the matched array item in the query". Use this to find an array member and then manipulate it. For example:

> 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 } ] }

現在のところ、 $ オペレータは、 クエリでマッチしたアイテムの 最初 のものにのみ適用されます。たとえば、

> t.find();
{ "_id" : ObjectId("4b9e4a1fc583fa1c76198319"), "x" : [ 1, 2, 3, 2 ] }
> t.update({x: 2}, {$inc: {"x.$": 1}}, false, true);
> t.find();
{ "_id" : ObjectId("4b9e4a1fc583fa1c76198319"), "x" : [ 1, 3, 3, 2 ] }

upsert と modifier

modifierオペレーションと一緒にupsertを使うことができます。このケースでは、modifier は criteria でアップデート対象のものに適用されます。そしてinsertされたオブジェクトを返します。次に、 upsertで {name:"Joe",x:1,y:1} を insertする例を示します。

db.people.update( { name:"Joe" }, { $inc: { x:1, y:1 } }, true );

いくつかの制限があります。modifierは、 _id フィールドを参照できません。またupdate内の2つ以上のmodifierが同じフィールドを参照できません。たとえば、次の例はできません。

db.people.update( { name:"Joe" }, { $inc: { x: 1 }, $set: { x: 5 } } );

ユニークな値を追加

存在していない場合にだけ、arrayに値を追加するには、

バージョン1.3.3から、次のようにできます。

update( {_id:'joe'},{"$addToSet": { tags : "baseball" } } );

それより古いバージョンでは、 $ne : <value> をクエリーに加えてください。

update( {_id:'joe', tags: {"$ne": "baseball"}}, 
{"$push": { tags : "baseball" } } ); 

updateリクエストの結果の確認

ここまでで紹介したように、 upsert以外のアップデートは存在するオブジェクトをupdateする場合とupdateしない場合があります。upsertは、存在するオブジェクトを更新するか、新しいオブジェクトを追加します。クライアントは、 getlasterror コマンド( db.runCommand( "getlasterror" ) )を続けて実行することで、そのコネクションで起こった直近のコマンドがオブジェクトをアップデートしたかどうかを判断することができます。 getlasterror コマンドの結果が、 updatedExisting を含んでいる場合、 このコネクションでの最後のコマンドは、updateリクエストだった、ということになります。 また updatedExisting がtrueの場合、updateリクエストは既存のオブジェクトをupdateしたことになり、 updatedExisting がfalseの場合には、どのオブジェクトもアップデートされなかったことになります。

padding について

MongoDBで、オブジェクトを更新する場合、オブジェクトのサイズが増えない場合には、更新はin-place(同じ場所)で実行されます。これは、コレクションがたくさんのインデックスを持っている場合、insertのパフォーマンスのために有効です。

Mongoは、コレクション内のオブジェクトが増えているかどうかを学習し、もし増える傾向にある場合、今後のデータの移動を防ぐため、予備の空間(padding)を追加します。

参照


Enter labels to add to this page:
Please wait 
Looking for a label? Just start typing.

IF YOU HAVE A QUESTION, POST IT TO THE USER GROUP.

These pages are fine for comments, but for questions, your best bet will always be the MongoDB User Group.

blog comments powered by Disqus