MongoCollection
PHP Manual

MongoCollection::update

(PECL mongo >=0.9.0)

MongoCollection::update指定した条件にもとづいてレコードを更新する

説明

public bool|array MongoCollection::update ( array $criteria , array $new_object [, array $options = array() ] )

パラメータ

criteria

更新したいオブジェクトの条件。

new_object

マッチするレコードを更新するオブジェクト。

options

このパラメータは 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 が設定されていれば、更新の状態を表す配列を返します。 それ以外の場合は、配列が空でないかどうかを表す boolean 値を返します (空の配列は追加されません)。 配列のフィールドについては MongoCollection::insert() のドキュメントを参照ください。

エラー / 例外

"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.9 "safe" オプションを使っている場合の返り値の型が配列に変わりました。 配列にはエラー情報が含まれています。"safe" オプションを使わない場合は、今までどおり boolean のままです。
1.0.11 "safe" が設定されている場合は、"not master" エラーで接続を切断するようになりました。
1.2.0 timeout オプションが追加されました。
1.3.0 options パラメータで、boolean だけを渡して upsert を指定することができなくなりました。 同じことをするには array('upsert'' => true) としなければなりません。

例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)
}

$new_object が $ 演算子を含まない場合、upsert は渡されたフィールドだけの新しいドキュメントを作成します。これは、通常の update の挙動と同じです。 update で $ 演算子を使わなければ、ドキュメント全体が上書きされます。

<?php

$c
->drop();
$c->update(
    array(
"name" => "joe"),
    array(
"username" => "joe312""createdAt" => new MongoDate()), 
    array(
"upsert" => true)
);
var_dump($c->findOne());

?>

上の例の出力は、 たとえば以下のようになります。

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 コアメント を参照ください。


MongoCollection
PHP Manual