ドキュメント内の配列の更新
Overview
このガイドでは、次の配列アップデート演算子を使用して、ドキュメント内に埋め込まれた配列を変更する方法を学習できます。
位置演算子:
$
すべての位置演算子:
$[]
フィルタリングされた位置演算子:
$[<identifier>]
配列更新演算子のリストについては、サーバー マニュアル ドキュメントの「更新演算子 」を参照してください。
配列要素の指定
位置演算子は、アップデートする配列要素を指定します。これらの演算子を使用して、基準に一致する配列の最初の要素、すべての要素、または特定の要素にアップデートを適用できます。
位置演算子を使用して配列内の要素を指定するには、ドット表記を使用します。 ドット表記は、BSON オブジェクトを操作するためのプロパティ アクセス構文です。 詳しくは、「ドット表記 」を参照してください。
最初に一致する配列要素
クエリに一致する各ドキュメントの最初の配列要素をアップデートするには、$
の位置演算子を使用します。
位置演算子$
は、クエリに一致する配列を参照します。 この演算子を使用してネストされた配列を参照することはできません。 ネストされた配列にアクセスする場合は、フィルタリングされた位置演算子を使用します。
重要
ドライバーが $
を挿入ドキュメント内のフィールド名として扱うため、upsert
呼び出しでは、$
演算子を使用しないようにします。
例
この例では、次のサンプルドキュメントを使用して、最初に一致する配列要素をアップデートする方法を示しています。
{ _id: ..., entries: [ { x: false, y: 1 }, { x: "hello", y: 100 }, { x: "goodbye", y: 1000 } ] }
次のコードは、クエリに一致する最初の配列要素の値を増分する方法を示しています。
クエリは、x
の値が string
型である、entries
配列内の要素と一致しています。アップデートにより、最初の一致する要素の y
の値が 33
増加します。
// Query for all elements in entries array where the value of x is a string const query = { "entries.x": { $type : "string" } }; // On first matched element, increase value of y by 33 const updateDocument = { $inc: { "entries.$.y": 33 } }; // Execute the update operation const result = await myColl.updateOne(query, updateDocument);
アップデート操作を実行すると、ドキュメントは次のようになります。
{ _id: ..., entries: [ { x: false, y: 1 }, { x: "hello", y: 133 }, { x: "goodbye", y: 1000 } ] }
この例では、$
演算子がアップデートを適用する配列と一致するようにクエリに entries.x
フィールドを含めています。アップデートで $
演算子を使用しているときにクエリから entries.x
フィールドを省略すると、ドライバーは一致する配列を識別できず、次のエラーが発生します。
MongoServerError: The positional operator did not find the match needed from the query.
すべての配列要素の一致
クエリに一致する各ドキュメントのすべての配列要素をアップデートするには、すべての位置演算子 $[]
を使用します。
例
この例では、通話ログを説明する次のサンプルドキュメントを使用して、一致するすべての配列要素をアップデートする方法を示しています。
{ _id: ..., date: "5/15/2023", calls: [ { time: "10:08 AM", caller: "Mom", duration: 67 }, { time: "04:11 PM", caller: "Dad", duration: 121 }, { time: "06:36 PM", caller: "Grandpa", duration: 13 } ] }, { _id: ..., date: "5/16/2023", calls: [ { time: "11:47 AM", caller: "Mom", duration: 4 }, ] }
次のコードは、date
が "5/15/2023"
であるドキュメント内のすべての calls
配列エントリから duration
フィールドを除く方法を示しています。
// Query for all documents where date is the string "5/15/2023" const query = { date: "5/15/2023" }; // For each matched document, remove duration field from all entries in calls array const updateDocument = { $unset: { "calls.$[].duration": "" } }; // Execute the update operation const result = await myColl.updateOne(query, updateDocument);
アップデート操作を実行すると、ドキュメントは次のようになります。
{ _id: ..., date: "5/15/2023", calls: [ { time: "10:08 AM", caller: "Mom" }, { time: "04:11 PM", caller: "Dad" }, { time: "06:36 PM", caller: "Grandpa" } ] }, { _id: ..., date: "5/16/2023", calls: [ { time: "11:47 AM", caller: "Mom", duration: 4 }, ] }
複数の配列要素の一致
クエリに一致する各ドキュメントのすべての埋め込み配列要素をアップデートするには、フィルタリングされた位置演算子 $[<identifier>]
を使用します。
フィルタリングされた位置演算子 $[<identifier>]
は、アップデートドキュメント内の一致する配列要素を指定します。一致する配列要素を識別するには、この演算子を arrayFilters
オブジェクト内の <identifier>
とペアにします。
<identifier>
プレースホルダーは配列フィールドの要素を表しています。<identifier>
には小文字で始まり、英数字のみを含む値を選択する必要があります。
使用法
アップデート操作では、フィルタリングされた位置演算子を使用できます。アップデート操作では、クエリ、アップデートドキュメント、オプションでオプションオブジェクトがパラメーターとして使用されます。
次の手順では、アップデート操作でフィルタリングされた位置演算子を使用する方法について説明します。
アップデートドキュメントの形式は、次のようにします。
{ $<operator>: { "<array>.$[<identifier>].<arrayField>": <updateParameter> } } このアップデートドキュメントには、次のプレースホルダーが含まれています。
$<operator>
: 配列アップデート演算子<array>
: アップデートするドキュメント内の配列<identifier>
: フィルタリングされた位置演算子の識別子<arrayField>
: アップデートする<array>
配列要素のフィールド<updateParameter>
: アップデートを説明する値
arrayFilters
オブジェクトに一致する条件を追加します。このオブジェクトは、アップデートに含める配列要素を指定するクエリの配列です。このオブジェクトをoptions
パラメーターに設定します。arrayFilters: [ { "<identifier>.<arrayField1>": <updateParameter1> }, { "<identifier>.<arrayField2>": <updateParameter2> }, ... ] クエリ、アップデートドキュメント、オプションをアップデートメソッドに渡します。次のサンプルコードは、これらのパラメーターを使用して
updateOne()
メソッドを呼び出す方法を示しています。await myColl.updateOne(query, updateDocument, options);
例
この例では、特定のレシピの買い物リストを説明する以下のサンプルドキュメントを使用して、一致する特定の配列要素をアップデートする方法を示しています。
{ _id: ..., date: "11/12/2023", items: [ { item: "Scallions", quantity: 3, recipe: "Fried rice" }, { item: "Mangos", quantity: 4, recipe: "Salsa" }, { item: "Pork shoulder", quantity: 1, recipe: "Fried rice" }, { item: "Sesame oil", quantity: 1, recipe: "Fried rice" } ] }, { _id: ..., date: "11/20/2023", items: [ { item: "Coffee beans", quantity: 1, recipe: "Coffee" } ] }
"11/12/2023"
の買い物で、レシピのために購入する食材の量を増やしたいとします。食材が以下の条件をすべて満たす場合は、数量を 2 倍にします。
この食材は
"Fried rice"
レシピ用です。食材名に
"oil"
という単語は含まれていません。
一致する配列エントリの quantity
値を 2 倍にするには、次のコードに示すように、フィルタリングされた位置演算子を使用します。
// Query for all documents where date is the string "11/12/2023" const query = { date: "11/12/2023" }; // For each matched document, change the quantity of items to 2 const updateDocument = { $mul: { "items.$[i].quantity": 2 } }; // Update only non-oil items used for fried rice const options = { arrayFilters: [ { "i.recipe": "Fried rice", "i.item": { $not: { $regex: "oil" } }, } ] }; // Execute the update operation const result = await myColl.updateOne(query, updateDocument, options);
アップデートにより、条件に一致する食材の quantity
値が 2
倍になりました。"Sesame oil"
食材は arrayFilters
オブジェクトの条件に一致しなかったため、アップデートから除外されました。次のドキュメントでは、これらの変更が反映されています。
{ _id: ..., date: "11/12/2023", items: [ { item: "Scallions", quantity: 6, recipe: "Fried rice" }, { item: "Mangos", quantity: 4, recipe: "Salsa" }, { item: "Pork shoulder", quantity: 2, recipe: "Fried rice" }, { item: "Sesame oil", quantity: 1, recipe: "Fried rice" } ] }, { _id: ..., date: "11/20/2023", items: [ { item: "Coffee beans", quantity: 1, recipe: "Coffee" } ] }