更新

更新は、MongoDB でできる操作の中でも最も複雑なもののひとつです。 これは、クエリの実行とその条件にマッチしたドキュメントへの操作を組み合わせたものです。 更新操作はきわめて強力なものでもあり、 ドキュメントの内容を手早く変更したり置き換えたりすることができます。 また、(可能なら) その場で、少ないオーバーヘッドで実行することができます。

ドキュメントの変更と置換

更新に使える方法は、二通りあります。変更による更新と、置換による更新です。 変更による更新は $ 演算子を含み、ドキュメント内のフィールドを変更します。 カウンタを増加させたり配列に新しい要素を追加したり、フィールドの型を変更したりといった更新がこれにあたります。

たとえば、変更による更新ではドキュメントに新たなフィールドを追加することができます。

<?php
/** このようなドキュメントを前提としています
 * {"username" : "...", "password" : "...", "email" : "..."}
 */
$coll->update(array("username" => "joe"), array('$set' => array("twitter" => "@joe4153")));

/** この結果、ドキュメントは次のようになります
 * {"username" : "joe", "password" : "...", "email" : "...", "twitter" : "@joe4153"}
 */
?>

置換による更新は、マッチしたドキュメント全体を新しいドキュメントで置き換えます。 $ 演算子を使った更新よりも非効率的ですが、複雑な操作や $ 演算子で表現できないような更新などでは非常に便利です。

たとえば、置換による更新ではドキュメントの構造を完全に変更してしまうことができます。

<?php
/** このようなドキュメントを前提としています
 * {"username" : "...", "password" : "...", "email" : "..."}
 */
$coll->update(array("username" => "joe"), array("userId" => 12345"info" => array(
    
"name" => "joe""twitter" => "@joe4153""email" => "..."), "likes" => array()));

/** この結果、ドキュメントは次のようになります
 * {
 *     "userId" : 12345, 
 *     "info" : {
 *         "name" : "joe", 
 *         "twitter" : "@joe4153", 
 *         "email" : "..."
 *     },
 *     "likes" : []
 * }
 */
?>

ネストしたオブジェクトの更新

次のドキュメントで、コメントの作者名を変更したいとします。

{ 
    "_id" : ObjectId("4b06c282edb87a281e09dad9"), 
    "content" : "this is a blog post.",
    "comments" : 
    [
        {
            "author" : "Mike",
            "comment" : "I think that blah blah blah...",
        },
        {
            "author" : "John",
            "comment" : "I disagree."
        }
    ]
}
内部のフィールドを変更するには、$set を使って (その他のフィールドを削除してしまわないように) 変更したいコメントのインデックスを指定します。
<?php

$blog
->update($criteria, array('$set' => array("comments.1" => array("author" => "Jim"))));

?>

位置演算子

位置演算子 $ は、配列内のオブジェクトを更新するときに便利です。 上の例で、変更したいコメントのインデックスがわからず 単に "John" を "Jim" に変更したいといった場合を考えましょう。 そのためには $ を使います。

<?php

$blog
->update(
    array(
"comments.author" => "John"), 
    array(
'$set' => array('comments.$.author' => "Jim")));

?>