$ (update)
定義
$
位置演算子
$
は、配列内の要素の位置を明示的に指定せずに、更新する配列内の要素を識別します。注意
曖昧さ回避
読み取り操作から配列要素をプロジェクションするか、または返すには、代わりに「
$
プロジェクション演算子」を参照してください。配列内のすべての要素をアップデートするには、代わりにすべての位置演算子
$[]
を参照してください。1 つまたは複数の配列フィルター条件に一致するすべての要素を更新するには、
$[<identifier>]
の代わりにフィルタリングされた位置演算子を参照してください。
互換性
次の環境でホストされる配置では、位置オペレーター$
を使用できます。
MongoDB Atlas はクラウドでの MongoDB 配置のためのフルマネージド サービスです
MongoDB Enterprise: サブスクリプションベースの自己管理型 MongoDB バージョン
MongoDB Community: ソースが利用可能で、無料で使用できる自己管理型の MongoDB のバージョン
構文
位置演算子 $
の形式は次のとおりです。
{ "<array>.$" : value }
更新操作で使用する場合、db.collection.updateOne()
とdb.collection.findAndModify()
、
位置演算子
$
はquery document
に一致する最初の要素のプレースホルダーとして機能し、array
フィールドはquery document
の一部として出現する必要があります。
以下に例を挙げます。
db.collection.updateOne( { <array>: value ... }, { <update operator>: { "<array>.$" : value } } )
動作
MongoDB 5.0 以降、更新演算子では名前が文字列ベースのドキュメントフィールドを辞書順に処理します。数値名のフィールドは、数値順に処理されます。詳細については、「更新演算子の動作」を参照してください。
upsert
挿入では、挿入されたドキュメントのフィールド名として $
が使用されるため、位置演算子 $
を アップサート 操作で使用しないでください。
ネストされた配列
位置演算子 $
は、$
プレースホルダーの置換が単一の値であるため、複数の配列を走査するクエリ(他の配列内にネストされた配列を走査するクエリなど)には使用できません
設定解除
$unset
演算子とともに使用した場合、位置指定の$
演算子は一致する要素を配列から削除せず、それをnull
に設定します。
除外
クエリが$ne
、 $not
、 $nin
などの否定演算子を使用して配列と一致する場合、位置演算子を使用してこの配列の値を更新することはできません。
ただし、クエリの否定部分が$elemMatch
式内にある場合は、位置演算子を使用したこのフィールドの更新が可能です。
複数の配列の一致
位置更新演算子 $
は、複数の配列フィールドをフィルタリングするときにあいまいな動作をします。
サーバーがアップデート メソッドを実行する際は、まずクエリを実行してアップデートするドキュメントを決定します。 更新で複数の配列フィールドのドキュメントがフィルタリングされる場合、位置指定の$
更新演算子に対する後続の呼び出しでは、配列内の必要な位置が必ずしも更新されるわけではありません。
詳細については、例を参照してください。
例
配列内の値を更新
次のドキュメントを使用してコレクション students
を作成します。
db.students.insertMany( [ { "_id" : 1, "grades" : [ 85, 80, 80 ] }, { "_id" : 2, "grades" : [ 88, 90, 92 ] }, { "_id" : 3, "grades" : [ 85, 100, 90 ] } ] )
grades
配列内の値が 80
である最初の要素を 82
に更新する場合、配列内の要素の位置が不明なときは、次のように位置演算子 $
を使用します。
重要
配列フィールドをquery
ドキュメントの一部として含める必要があります。
db.students.updateOne( { _id: 1, grades: 80 }, { $set: { "grades.$" : 82 } } )
位置演算子 は、アップデート$
クエリ ドキュメント の 最初の一致 のプレースホルダーとして機能し 。
操作後、students
コレクションには次のドキュメントが含まれます。
{ "_id" : 1, "grades" : [ 85, 82, 80 ] } { "_id" : 2, "grades" : [ 88, 90, 92 ] } { "_id" : 3, "grades" : [ 85, 100, 90 ] }
配列内のドキュメントを更新
位置演算子 $
は、埋め込みドキュメントを含む配列の更新を容易にします。位置演算子 $
を使用して $
演算子上のドット表記の埋め込みドキュメント内のフィールドにアクセスします。
db.collection.updateOne( { <query selector> }, { <update operator>: { "array.$.field" : value } } )
students
コレクション内の grades
要素の値が埋め込みドキュメントの配列である次のドキュメントを考えます。
{ _id: 4, grades: [ { grade: 80, mean: 75, std: 8 }, { grade: 85, mean: 90, std: 5 }, { grade: 85, mean: 85, std: 8 } ] }
位置指定の$
演算子を使用して、 grade
が85
に等しい条件に一致する最初の配列要素のstd
フィールドを更新します。
重要
配列フィールドをquery
ドキュメントの一部として含める必要があります。
db.students.updateOne( { _id: 4, "grades.grade": 85 }, { $set: { "grades.$.std" : 6 } } )
操作後、ドキュメントには次の更新された値が含まれます。
{ "_id" : 4, "grades" : [ { "grade" : 80, "mean" : 75, "std" : 8 }, { "grade" : 85, "mean" : 90, "std" : 6 }, { "grade" : 85, "mean" : 85, "std" : 8 } ] }
複数のフィールド一致を使用した埋め込みドキュメントの更新
$
演算子は、$elemMatch
演算子で指定された複数のクエリ条件に一致する最初の配列要素を更新できます。
students
コレクション内の grades
フィールド値が埋め込みドキュメントの配列である次のドキュメントを考えます。
{ _id: 5, grades: [ { grade: 80, mean: 75, std: 8 }, { grade: 85, mean: 90, std: 5 }, { grade: 90, mean: 85, std: 3 } ] }
以下の例では、$
演算子は、grade
フィールドの値が 90
以下で、mean
フィールドの値が 80
より大きい最初の埋め込みドキュメントの std
フィールドの値を更新します。
db.students.updateOne( { _id: 5, grades: { $elemMatch: { grade: { $lte: 90 }, mean: { $gt: 80 } } } }, { $set: { "grades.$.std" : 6 } } )
この操作は、条件に一致する最初の埋め込みドキュメント、つまり配列内の 2 番目の埋め込みドキュメントを更新します。
{ _id: 5, grades: [ { grade: 80, mean: 75, std: 8 }, { grade: 85, mean: 90, std: 6 }, { grade: 90, mean: 85, std: 3 } ] }
複数の配列の一致による更新
クエリにコレクション内のドキュメントをフィルタリングするための複数のフィールドがある場合、更新用の位置演算子 $
の動作はあいまいになります。
学生情報の配列を保持するstudents_deans_list
コレクション内のドキュメントを検討します。
db.students_deans_list.insertMany( [ { _id: 8, activity_ids: [ 1, 2 ], grades: [ 90, 95 ], deans_list: [ 2021, 2020 ] } ] )
次の例では、ユーザーは deans_list
フィールドの変更を試み、 activity_ids
、 deans_list
、および grades
フィールドを使用してドキュメントをフィルタリングし、 deans_list
フィールドの 2021 の値を 2022 に更新します。
db.students_deans_list.updateOne( { activity_ids: 1, grades: 95, deans_list: 2021 }, { $set: { "deans_list.$": 2022 } } )
サーバーが上記の updateOne
メソッドを実行するときに、指定された配列フィールド内の値を使用して使用可能なドキュメントをフィルタリングします。deans_list
フィールドはフィルターで使用されますが、配列内の更新位置を決定するために更新用の位置演算子 $
によって使用されるフィールドではありません。
db.students_deans_list.find( { _id: 8 } )
出力例:
{ _id: 8, activity_ids: [ 1, 2 ], grades: [ 90, 95 ], deans_list: [ 2021, 2022 ] }
updateOne
メソッドは 2021 上の deans_list
フィールドと一致しましたが、更新用の位置演算子 $
は代わりに 2020 の値を 2022 に変更しました。
複数の配列を照合するときに予期しない結果にならないように、代わりにフィルターされた位置演算子$[<identifier>]
を使用します。