MongoDB
 Computer >> コンピューター >  >> プログラミング >> MongoDB

MongoDBでドキュメント配列内のオブジェクトを更新する方法(ネストされた更新)

MongoDBでは、ドキュメント内の配列に格納されたオブジェクト(ネストされた要素)を更新するには、update()メソッドと位置演算子「$」を組み合わせて使用します。本記事では、実際にコレクションを作成しながら、配列内の特定のオブジェクトを更新する手順をわかりやすく解説します。

サンプルコレクションの作成

まず、insertOne()メソッドを使って、配列フィールドを持つドキュメントを含むコレクションを作成します。以下のクエリを実行してください。

> db.updateObjects.insertOne({"CustomerId":1,"CustomerName":"Larry","TotalItems":100,
... "ItemDetails":[
... {
... "NameOfItem":"Item_1",
... "Amount":450
... },
... {
... "NameOfItem":"Item_2",
... "Amount":500
... },
... {
... "NameOfItem":"Item_3",
... "Amount":200
... }
... ]
... }
... );

実行すると、次のような出力が返されます。

{
    "acknowledged" : true,
    "insertedId" : ObjectId("5c6d688b0c3d5054b766a769")
}

このコレクションには、顧客情報とともに「ItemDetails」という配列フィールドがあり、その中に複数の商品オブジェクト(品名と金額)がネストして格納されています。

find()メソッドでドキュメントを確認

find()メソッドを使うと、コレクション内のドキュメントを表示できます。以下のクエリを実行してみましょう。

> db.updateObjects.find().pretty();

出力結果は次のとおりです。

{
    "_id" : ObjectId("5c6d688b0c3d5054b766a769"),
    "CustomerId" : 1,
    "CustomerName" : "Larry",
    "TotalItems" : 100,
    "ItemDetails" : [
        {
            "NameOfItem" : "Item_1",
            "Amount" : 450
        },
        {
            "NameOfItem" : "Item_2",
            "Amount" : 500
        },
        {
            "NameOfItem" : "Item_3",
            "Amount" : 200
        }
    ]
}

$inc演算子と位置演算子$で配列内の値を更新

ここで、「Item_3」の「Amount」フィールドの値200を、130だけ加算してみます。このような場合、フィールドの値を増加させる$inc演算子と、条件に一致した配列要素を指し示す位置演算子「$」を使用します。

クエリは以下のようになります。

> db.updateObjects.update({"CustomerId":1,"ItemDetails.NameOfItem":"Item_3"},
{$inc:{"ItemDetails.$.Amount":130}},
... false,true);
WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })

このクエリのポイントは次のとおりです。

  • 検索条件に「ItemDetails.NameOfItem:"Item_3"」を指定することで、配列内の該当オブジェクトを特定しています。
  • ItemDetails.$.Amount」のようにパスに「$」を付けることで、条件に一致した配列要素だけが更新対象になります。
  • 第3引数のfalseはアップサートなし、第4引数のtrueは複数ドキュメントの更新を意味します。

結果として「nModified : 1」と表示され、更新が正常に完了したことがわかります。

更新後のドキュメントを確認

再度find()メソッドを実行して、更新結果を確認しましょう。

> db.updateObjects.find().pretty();

出力結果は次のとおりです。

{
    "_id" : ObjectId("5c6d688b0c3d5054b766a769"),
    "CustomerId" : 1,
    "CustomerName" : "Larry",
    "TotalItems" : 100,
    "ItemDetails" : [
        {
            "NameOfItem" : "Item_1",
            "Amount" : 450
        },
        {
            "NameOfItem" : "Item_2",
            "Amount" : 500
        },
        {
            "NameOfItem" : "Item_3",
            "Amount" : 330
        }
    ]
}

出力を見ると、「Item_3」のAmountが200から130増加し、330になっていることが確認できます。他の配列要素(Item_1、Item_2)には影響を与えていない点にも注目してください。

補足:新しいバージョンでの推奨メソッド

MongoDBの新しいバージョンでは、update()メソッドは非推奨となっており、代わりにupdateOne()updateMany()の使用が推奨されています。上記の例は、updateOne()を使って次のように書き換えることができます。

> db.updateObjects.updateOne(
... {"CustomerId":1,"ItemDetails.NameOfItem":"Item_3"},
... {$inc:{"ItemDetails.$.Amount":130}}
... );

基本的な構文や位置演算子「$」の使い方は同じなので、これまでの知識をそのまま活かせます。

まとめ

MongoDBでドキュメント配列内のオブジェクトを更新する際は、検索条件で配列内のフィールドを指定し、更新パスに位置演算子「$」を使用するのがポイントです。$inc以外にも$setなどの更新演算子と組み合わせることで、柔軟なネストされた更新が可能になります。

  1. MongoDBで条件に一致する複数のドキュメントを一括更新する方法(multiオプションの使い方)

    MongoDBのupdate()メソッドは、デフォルトでは条件に一致した最初の1件のドキュメントしか更新しません。条件に一致する複数のドキュメントをまとめて更新したい場合は、第3引数に{ multi: true }を指定します。この記事では、実際にコレクションを作成しながら、multiオプションを使った部分一括更新の手順を解説します。1. サンプルコレクションの作成まず、insertOne()メソッドを使って、テスト用のコレクションにドキュメントを挿入します。> db.demo312.insertOne({FirstName:Robert}); { acknowledged : t

  2. MongoDBでオブジェクト配列内の特定のネストされたドキュメントをクエリする方法

    MongoDBでオブジェクトの配列からネストされたドキュメントを抽出する オブジェクトの配列に格納されたネストされたドキュメントを条件付きで検索したい場合、find()メソッドに$elemMatch演算子を組み合わせることで、指定した条件に一致する要素だけを取り出すことができます。 ここでは、「StudentAge」フィールドを持つ学生情報だけを配列から抽出する例を見ていきましょう。 1. サンプルコレクションの作成 まず、ドキュメントを挿入してコレクションを作成します。このコレクションには、学生情報がオブジェクトの配列として格納されています。 > db.demo763.insertO