(PECL mongo >=0.9.0)
MongoCollection::update — 指定した条件にもとづいてレコードを更新する
更新したいオブジェクトの条件。
マッチするレコードを更新するオブジェクト。
このパラメータは array("optionname" => <boolean>, ...) 形式の連想配列で、現在サポートしているオプションは次の通りです。
"upsert"
$criteria にマッチするレコードが見つからない場合に $criteria と $newobj から新しいオブジェクトを作ります (以下の upsert の例を参照ください)。
"multiple"
$criteria にマッチするすべてのドキュメントを更新します。 MongoCollection::update() は MongoCollection::remove() と正反対の動きをします。 デフォルトでは、マッチするすべてのドキュメントではなく ひとつのドキュメントだけを更新するのです。 複数ドキュメントを更新したいのかそうでないのかは、 常に指定しておくことを推奨します。 将来、データベースのデフォルトの挙動が変わる可能性があるからです。
"safe"
boolean あるいは整数値で、デフォルトは FALSE です。FALSE の場合、データベースからの応答を待たずにプログラムを続行します。 TRUE の場合、プログラムはデータベースからの応答を待ち、 更新に失敗したときには MongoCursorException をスローします。
レプリケーションを使っていてマスタを変更している場合、もし "safe" を使っていればドライバはマスタとの接続を切断して例外をスローし、 次の操作時に新しいマスタを探そうとします (新しいマスタに対して操作を再試行するかどうかは アプリケーション側で判断しなければなりません)。
レプリカセットで "safe" を 使わずに マスタを変更する場合は、ドライバがその変更について知るすべがありません。 そのため、何もエラーを出さずに書き込みに失敗し続けます。
safe が整数値の場合は、 指定した数のマシンで更新が成功するまでは成功したと見なしません (処理がタイムアウトした場合は例外をスローします。wtimeout を参照ください)。 これは、コレクションに設定された w 変数をオーバーライドします。
"fsync"
boolean で、デフォルトは FALSE です。 更新操作がディスク上に同期されるまで成功とは見なさないようにさせます。 TRUE の場合は "安全な" 追加操作が前提となり、 safe の設定を FALSE にオーバーライドします。
"timeout"
整数値。デフォルトは MongoCursor::$timeout です。 "safe" が設定されている場合に、クライアントがデータベースからの応答をどれだけ待つかを (ミリ秒単位で) 指定します。ここで指定した時間内にデータベースからの応答がない場合は MongoCursorTimeoutException がスローされます。
更新のデータベースへの送信が成功したかどうかを返します。
"safe" オプションが設定されているときに更新に失敗した場合は、 MongoCursorException をスローします。
"safe" オプションが設定されているときに MongoCollection::$wtimeout ミリ秒以内に処理が終わらなければ MongoCursorTimeoutException をスローします。 これはサーバ上の操作を終了させるわけではなく、あくまでもクライアント側のタイムアウトです。
バージョン | 説明 |
---|---|
1.0.1 | "options" パラメータが boolean から配列に変わりました。 1.0.1 より前のバージョンでは二番目のパラメータはオプションの boolean 値で、upsert を指定するものでした。 |
1.0.5 | "safe" オプションが追加されました。 |
1.0.9 | "safe" オプションに整数値がわたせるようになり (以前は booleans のみでした)、さらに "fsync" オプションが追加されました。 |
1.0.11 | "safe" が設定されている場合は、"not master" エラーで接続を切断するようになりました。 |
1.2.0 | timeout オプションが追加されました。 |
例1 MongoCollection::update()
address フィールドをドキュメントに追加します。
<?php
$c->insert(array("firstname" => "Bob", "lastname" => "Jones" ));
$newdata = array('$set' => array("address" => "1 Smith Lane"));
$c->update(array("firstname" => "Bob"), $newdata);
var_dump($c->findOne(array("firstname" => "Bob")));
?>
上の例の出力は、 たとえば以下のようになります。
array(4) { ["_id"]=> object(MongoId)#6 (0) { } ["firstname"]=> string(3) "Bob" ["lastname"]=> string(5) "Jones" ["address"]=> string(12) "1 Smith Lane" }
例2 MongoCollection::update() での upsert
upsert を使うとコードを簡潔にすることができます。 オブジェクトが存在しない場合は新たに作成し、 存在する場合はそれを更新するという操作を一行で書けるからです。
<?php
$c->drop();
$c->update(array("uri" => "/summer_pics"), array('$inc' => array("page hits" => 1)), array("upsert" => true));
var_dump($c->findOne());
?>
上の例の出力は、 たとえば以下のようになります。
array(3) { ["_id"]=> object(MongoId)#9 (0) { } ["uri"]=> string(12) "/summer_pics" ["page hits"]=> int(1) }
newobj が $ 演算子を含まない場合、upsert は新しいドキュメントを単体で作成します。これは、通常の update の挙動と同じです。 update で $ 演算子を使わなければ、ドキュメント全体が上書きされます。
<?php
$c->update(array("name" => "joe"), array("username" => "joe312", "createdAt" => new MongoDate()),
array("upsert" => true));
?>
上の例の出力は、 たとえば以下のようになります。
array(3) { ["_id"]=> object(MongoId)#10 (0) { } ["username"]=> string(6) "joe312" ["createdAt"]=> object(MongoDate)#4 (0) { } }
例3 MongoCollection::update() での複数更新
デフォルトでは MongoCollection::update() は、 $criteria にマッチするドキュメントが複数見つかっても最初のものだけを更新します。 必要なら、"multiple" オプションでその挙動を変えることができます。
この例は、翌日が誕生日である全員に "gift" フィールドを追加します。
<?php
$today = array('$gt' => new MongoDate(), '$lt' => new MongoDate(strtotime("+1 day")));
$people->update(array("birthday" => $today), array('$set' => array('gift' => $surprise)), array("multiple" => true));
?>
更新に関するドキュメント および » MongoDB コアメント を参照ください。