Docs Menu
Docs Home
/
MongoDBマニュアル
/ / /

update

項目一覧

  • 定義
  • 互換性
  • 構文
  • コマンドフィールド
  • アクセス制御
  • 動作
  • 出力
update

updateコマンドは、コレクション内のドキュメントを変更します。 単一のupdateコマンドに複数のアップデート ステートメントを含めることができます。

Tip

mongosh では、このコマンドはupdateOne()updateMany()replaceOne()findOneAndReplace() 、およびヘルパー メソッド findOneAndUpdate()を通じて実行することもできます。

ヘルパー メソッドはmongoshユーザーには便利ですが、データベースコマンドと同じレベルの情報は返されない可能性があります。 便宜上必要ない場合、または追加の戻りフィールドが必要な場合は、 データベースコマンドを使用します。

このコマンドは、次の環境でホストされている配置で使用できます。

  • MongoDB Atlas はクラウドでの MongoDB 配置のためのフルマネージド サービスです

注意

このコマンドは、すべての MongoDB Atlas クラスターでサポートされています。すべてのコマンドに対する Atlas のサポートについては、「サポートされていないコマンド」を参照してください。

  • MongoDB Enterprise: サブスクリプションベースの自己管理型 MongoDB バージョン

  • MongoDB Community: ソースが利用可能で、無料で使用できる自己管理型の MongoDB のバージョン

バージョン 5.0 での変更

このコマンドの構文は、次のとおりです。

db.runCommand(
{
update: <collection>,
updates: [
{
q: <query>,
u: <document or pipeline>,
c: <document>, // Added in MongoDB 5.0
upsert: <boolean>,
multi: <boolean>,
collation: <document>,
arrayFilters: <array>,
hint: <document|string>
},
...
],
ordered: <boolean>,
maxTimeMS: <integer>,
writeConcern: { <write concern> },
bypassDocumentValidation: <boolean>,
comment: <any>,
let: <document> // Added in MongoDB 5.0
}
)

このコマンドは、次のフィールドを使用します。

フィールド
タイプ
説明
update
string
ターゲット コレクションの名前。
updates
配列
名前付きコレクションに対して実行する 1 つ以上のアップデート ステートメントの配列。 更新 ステートメントの詳細については、「 更新 ステートメント 」を参照してください
ordered
ブール値
オプション。true の場合、アップデート ステートメントが失敗すると、残りのアップデート ステートメントを実行せずに戻ります。false の場合、アップデートが失敗すると、残りのアップデートス テートメントがあればそれを続行します。デフォルトは true です。
maxTimeMS
non-negative integer

任意。

時間制限をミリ秒単位で指定します。maxTimeMS の値を指定しない場合、操作はタイムアウトしません。値を 0 にすると、デフォルトの無制限動作を明示的に指定します。

MongoDB は、db.killOp() と同じメカニズムを使用して、割り当てられた時間制限を超えた操作を終了します。MongoDB は、指定された割り込みポイントのいずれかでのみ操作を終了します。

writeConcern
ドキュメント

任意。update コマンドの書込み保証(write concern)を表すドキュメント。デフォルトの書込み保証を使用する場合は省略します。

トランザクションで実行される場合、操作の書込み保証 (write concern)を明示的に設定しないでください。トランザクションで書込み保証を使用するには、「トランザクション書込み保証」を参照してください。

bypassDocumentValidation
ブール値
任意。 操作中にupdateがドキュメント検証をバイパスできるようにします。 これにより、検証要件を満たさないドキュメントを更新できるようになります。
comment
any

任意。このコマンドに添付するユーザー指定のコメント。設定すると、このコメントは以下の場所にこのコマンドの記録と合わせて表示されます。

コメントには、有効な BSON 型(string, integer, object, array など)を使用できます。

ドキュメント

任意。

変数のリストを含むドキュメントを指定します。これにより、変数をクエリテキストから分離することで、コマンドの読みやすさを向上させることができます。

ドキュメントの構文は次のとおりです。

{
<variable_name_1>: <expression_1>,
...,
<variable_name_n>: <expression_n>
}

変数は式によって返された値に設定され、その後は変更できません。

コマンド内の変数の値にアクセスするには、二重ドル記号の接頭辞($$)を $$<variable_name> 形式にした変数名とともに使用します。たとえば次のとおりです。$$targetTotal

完全な例については、「 letオプションまたはcフィールドでの変数の使用 」を参照してください。

バージョン 5.0 で追加

updates配列の各要素は、アップデート ステートメント ドキュメントです。各ドキュメントには、次のフィールドが含まれています。

フィールド
タイプ
説明
ドキュメント

アップデートするドキュメントに一致するクエリ。find() メソッドで使用されているのと同じクエリ セレクター を使用します。

ドキュメントまたはパイプライン

適用される修正。値は次のいずれかになります。

詳細については、「動作」を参照してください。

ドキュメント

オプション。u がパイプラインの場合にのみ c を指定できます。

変数のリストを含むドキュメントを指定します。これにより、変数をクエリテキストから分離することで、コマンドの読みやすさを向上させることができます。

ドキュメントの構文は次のとおりです。

{
<variable_name_1>: <expression_1>,
...,
<variable_name_n>: <expression_n>
}

変数は式によって返された値に設定され、その後は変更できません。

コマンド内の変数の値にアクセスするには、二重ドル記号の接頭辞($$)を $$<variable_name> 形式にした変数名とともに使用します。たとえば次のとおりです。$$targetTotal

結果のフィルタリングに変数を使用するには、$expr 演算子内の変数にアクセスする必要があります。

let と変数を使用する完全な例については、 letオプションまたはcフィールドで変数を使用する」を参照してください。

バージョン 5.0 で追加

ブール値

任意。true の場合、update によって次のいずれかが実行されます。

  • query に一致するドキュメントがない場合は、新しいドキュメントを作成します。詳しくは、「アップサートの動作」を参照してください。

  • query に一致する 1 つのドキュメントをアップデートします。

upsertmulti の両方が true であり、クエリに一致するドキュメントがない場合、アップデート操作によって 1 つのドキュメントのみが挿入されます。

複数のアップサートを回避するため、query フィールドにユニークインデックスが付けられていることを確認します。例については、「ユニークインデックスを使用したアップサート」を参照してください。

デフォルトは false で、一致するものが見つからなくても新しいドキュメントは挿入されません

multi
ブール値

オプション。true の場合、クエリ条件を満たすすべてのドキュメントを更新します。false の場合、クエリ条件を満たす 1 つのドキュメントに更新を制限します。デフォルトは false です。

複数のドキュメントをアップデートする場合、1 つのドキュメントがアップデートに失敗すると、それ以降のドキュメントはアップデートされません。この動作の詳細については、「Multiアップデートの失敗」を参照してください。

collation
ドキュメント

任意。

操作に使用する照合を指定します。

照合を指定すると、大文字・小文字やアクセント記号など、文字列を比較するための言語独自のルールを指定できます。

照合オプションの構文は次のとおりです。

collation: {
locale: <string>,
caseLevel: <boolean>,
caseFirst: <string>,
strength: <int>,
numericOrdering: <boolean>,
alternate: <string>,
maxVariable: <string>,
backwards: <boolean>
}

照合を指定する場合、locale フィールドは必須ですが、その他の照合フィールドはすべて任意です。フィールドの説明については、照合ドキュメントを参照してください。

照合が指定されていなくても、コレクションにデフォルトの照合が設定されている場合(db.createCollection() を参照)には、コレクションの照合が使用されます。

コレクションにも操作にも照合が指定されていない場合、MongoDB では以前のバージョンで使用されていた単純なバイナリ比較によって文字列が比較されます。

1 つの操作に複数の照合は指定できません。たとえば、フィールドごとに異なる照合を指定できません。また、ソートと検索を一度に実行する場合、検索とソートで別の照合を使用できません。

arrayFilters
配列

オプション。配列フィールドのアップデート操作でどの配列要素を変更するかを決定するフィルタードキュメントの配列。

アップデート ドキュメントでは、$[<identifier>] フィルター処理された位置演算子を使用して識別子を定義し、配列フィルター ドキュメントで参照します。識別子がアップデートドキュメントに含まれていない場合、識別子の配列フィルタードキュメントを作成することはできません。

<identifier>は小文字で始まり、含めることができるのは英数字のみです。

アップデート ドキュメントには同じ識別子を複数回含めることができます。ただし、アップデート ドキュメント内の個別の識別子 ($[identifier]) それぞれに対し、対応する配列フィルター ドキュメントを 1 つだけ指定する必要があります。つまり、同じ識別子に対して複数の配列フィルター ドキュメントを指定することはできません。たとえば、アップデート ステートメントに識別子 x が(場合によっては複数回)含まれている場合、x に 2 つの個別のフィルタ ドキュメントを含む arrayFilters に対して、次のように指定することはできません。

// INVALID
[
{ "x.a": { $gt: 85 } },
{ "x.b": { $gt: 80 } }
]

ただし、次の例のように、単一のフィルター ドキュメント内の同じ識別子に複合条件を指定できます。

// Example 1
[
{ $or: [{"x.a": {$gt: 85}}, {"x.b": {$gt: 80}}] }
]
// Example 2
[
{ $and: [{"x.a": {$gt: 85}}, {"x.b": {$gt: 80}}] }
]
// Example 3
[
{ "x.a": { $gt: 85 }, "x.b": { $gt: 80 } }
]

例については、「配列アップデート操作にarrayFiltersを指定する」を参照してください。

ドキュメントまたは文字列

任意。 クエリ述語 をサポートするために使用する インデックス を指定するドキュメントまたは string です。

このオプションには、インデックス仕様ドキュメントまたはインデックス名の文字列を指定できます。

存在しないインデックスを指定した場合、操作はエラーになります。

例については、「更新操作での hint の指定」を参照してください。

このコマンドは、操作のステータスを含むドキュメントを返します。例:

{
"ok" : 1,
"nModified" : 0,
"n" : 1,
"upserted" : [
{
"index" : 0,
"_id" : ObjectId("52ccb2118908ccd753d65882")
}
]
}

出力フィールドの詳細については、「出力」を参照してください。

authorizationを使用して実行されている配置では、ユーザーには次の特権を含むアクセス権が必要です。

  • update 指定したコレクションに対するアクション。

  • find 指定したコレクションに対するアクション。

  • insert 指定したコレクションに対するアクション。

組み込みロール readWrite は必要な特権を提供します。

アップデートステートメントフィールド u は、 アップデート演算子式のみを含むドキュメントを受け入れることができます。例:

updates: [
{
q: <query>,
u: { $set: { status: "D" }, $inc: { quantity: 2 } },
...
},
...
]

次に、 updateコマンドはドキュメント内の対応するフィールドのみを更新します。

アップデート ステートメント フィールドuフィールドは置換ドキュメントを受け入れることができます。つまり、ドキュメントにはfield:valueのみが含まれます。 例:

updates: [
{
q: <query>,
u: { status: "D", quantity: 4 },
...
},
...
]

次に、 updateコマンドは一致するドキュメントをアップデート ドキュメントに置き換えます。 updateコマンドは一致するドキュメントを1 つだけ置き換えることができます。つまり、 multiフィールドはtrueにできません。 updateコマンドは_id値を置き換えません

multi パラメータがtrue に設定されたアップデートコマンドで 1 つのドキュメントのアップデートに失敗した場合、それ以上のドキュメントはそのコマンドの一部としてはアップデートされません。

たとえば、以下のドキュメントでmembersコレクションを作成する場合、

db.members.insertMany( [
{ "_id" : 1, "member" : "Taylor", "status" : "pending", "points" : 1},
{ "_id" : 2, "member" : "Alexis", "status" : "enrolled", "points" : 59},
{ "_id" : 3, "member" : "Elizabeth", "status" : "enrolled", "points" : 34}
] )

以下の操作では points の値が 60 と等しくなることはできないというルールで members コレクションにドキュメント検証を作成します。

db.runCommand( {
collMod: "members",
validator: { points: { $ne: 60 } }
} )

このアップデート コマンドにより、すべてのドキュメントの points フィールドの値を 1 増やします。

db.runCommand(
{
update: "members",
updates: [
{
q: {},
u: { $inc: { points: 1 } },
multi: true
}
]
}
)

コマンドの実行後、コレクションには次のドキュメントが含まれます。

{ _id: 1, member: 'Taylor', status: 'A', points: 2 }
{ _id: 2, member: 'Alexis', status: 'D', points: 59 }
{ _id: 3, member: 'Elizabeth', status: 'C', points: 34 }

update コマンドでは 1 番目のドキュメントの points の値がアップデートされましたが、2 番目のドキュメントはアップデートされませんでした。points の値は 60 と等しくならないという検証ルールによるものです。書き込みエラー以降はドキュメントが更新されないため、3 番目のドキュメントは更新されませんでした。

注意

一致したドキュメントのサブセットが更新された場合、たとえば、更新によって一部のドキュメントがスキーマ検証に失敗する場合、update コマンドによって返される nModified の値は正確ではない可能性があります。

アップデート ステートメント フィールド u フィールドでは、集計パイプライン[ <stage1>, <stage2>, ... ]を受け入れて、実行する変更を指定できます。パイプラインは、次のステージで構成できます。

集計パイプラインを使用すると、現在のフィールド値に基づいて条件付きのアップデートを表現したり、あるフィールドを他のフィールドの値を使用してアップデートするなど、より表現内容の多いアップデート ステートメントが可能になります。

以下に例を挙げます。

updates: [
{
q: <query>,
u: [
{ $set: { status: "Modified", comments: [ "$misc1", "$misc2" ] } },
{ $unset: [ "misc1", "misc2" ] }
],
...
},
...
]

注意

パイプライン内で使用される $set$unset は、集計ステージの$set$unset をそれぞれ示しており、アップデートの演算子の$set$unset ではありません。

例については、「集計パイプラインによる更新」を参照してください。

重複を防ぐためのユニークインデックスがない限り、アップサートによって重複したドキュメントが作成されることがあります。

Andy という名前のドキュメントが存在せず、複数のクライアントがほぼ同時に次のコマンドを発行する例を考えます。

db.runCommand(
{
update: "people",
updates: [
{ q: { name: "Andy" }, u: { $inc: { score: 1 } }, multi: true, upsert: true }
]
}
)

いずれかのクライアントがデータを正常に挿入する前にすべての update 操作がクエリ フェーズを終了し、かつ name フィールドにユニークインデックスがない場合、各 update 操作によって挿入が行われて、name: Andyを含む複数のドキュメントが作成される可能性があります。

name フィールドに一意なインデックスを設定すると、ドキュメントが 1 つだけ作成されるようになります。一意なインデックスが設定されると、複数の update 操作で次の動作が見られるようになります。

  • 正確に 1 つの update 操作で新しいドキュメントが正常に挿入されます。

  • その他の update 操作は、新しく挿入されたドキュメントを更新するか、一意なキーの競合が原因で失敗します。

    他の update 操作で新しく挿入されたドキュメントを更新するには、次の条件がすべて満たされている必要があります。

    • ターゲット コレクションに一意なインデックスがあるため、重複キー エラーが発生。

    • 更新操作が updateMany ではない、または multifalse

    • アップデートの一致条件は、次のいずれかです。

      • 単一の等価述語。例: { "fieldA" : "valueA" }

      • 等価述語の論理 AND。例: { "fieldA" : "valueA", "fieldB" : "valueB" }

    • 等価述語内のフィールドが、一意なインデックス キー パターン内のフィールドと一致。

    • 更新操作が、一意なインデックス キー パターン内のフィールドを変更しない。

次の表に示す upsert 操作の例では、キーの衝突が発生した場合に更新されるか失敗します。

ユニークインデックスキーのパターン
アップデート操作
結果
{ name : 1 }
db.people.updateOne(
{ name: "Andy" },
{ $inc: { score: 1 } },
{ upsert: true }
)
マッチしたドキュメントの score フィールドが 1 インクリメントされます。
{ name : 1 }
db.people.updateOne(
{ name: { $ne: "Joe" } },
{ $set: { name: "Andy" } },
{ upsert: true }
)
一意なインデックス キー パターン(name)のフィールドが変更されるため、操作は失敗します。
{ name : 1 }
db.people.updateOne(
{ name: "Andy", email: "andy@xyz.com" },
{ $set: { active: false } },
{ upsert: true }
)
等式述語フィールド(nameemail)がインデックス キー フィールド(name)と一致しないため、操作は失敗します。

updates 配列内の各アップデート要素について、クエリと更新サイズの合計(qおよびu )は、最大 BSON ドキュメント サイズ以下である必要があります。

updates 配列内の更新ステートメントの総数は、最大バルクサイズ以下である必要があります。

updateコマンドはbypassDocumentValidationオプションのサポートを追加します。これにより、検証ルールを使用してコレクションにドキュメントを挿入または更新するときにドキュメント検証をバイパスできます。

シャーディングされたコレクションでupdatemulti: falseと併用するには、

  • upsert: trueを指定しない場合、フィルターq_idフィールドに等価一致を含めるか、単一のシャードをターゲットにする(シャードキーを含めるなど)必要があります。

  • upsert: true を指定する場合、フィルターqにはシャードキーの等価一致が含まれている必要があります。

    ただし、シャーディングされたコレクション内のドキュメントにはシャードキーのフィールドがない場合があります。シャードキーがないドキュメントを対象とするには、null を等価一致の を(_id フィールド上と同じに)別のフィルター条件と組み合わせて使用できます。以下に例を挙げます。

    { _id: <value>, <shardkeyfield>: null } // _id of the document missing shard key

ドキュメントを置き換えるとき、 updateは最初にクエリフィルターを使用して、1 つのシャードをターゲットにしようとします。 クエリフィルターで単一のシャードをターゲットにできない場合は、置き換えドキュメントをターゲットにしようとします。

シャードキー フィールドが不変の _id フィールドでない限り、ドキュメントのシャードキー値を更新できます。

既存のシャードキー値をupdateで変更するには

Tip

欠落しているキー値は NULL 等価一致の一部として返されるため、NULL 値のキーが更新されないように、必要に応じて追加のクエリ条件(_id フィールドなど)を追加します。

シャーディングされたコレクションの upsert」も参照してください。

シャーディングされたコレクション内のドキュメントには、シャードキー フィールドがない場合がありますupdateを使用してドキュメントの欠落しているシャードキーを設定するには、mongosで実行する必要があります。シャードに対して直接操作を実行しないでください

さらに、次の要件も適用されます。

タスク
要件
設定するには null
  • multi: true を指定できます。

  • upsert: trueが指定されている場合は、完全なシャードキーに等価フィルターが必要です。

null 以外の値に設定するには、
  • トランザクション 内で、または再試行可能な書き込みとして実行する必要があります

  • 必ずmulti: falseを指定します。

  • 次のいずれかの場合、完全なシャードキーに等価フィルターが必要です。

    • upsert: trueまたは、

    • 置換ドキュメントを使用しており、新しいシャードキー値が別のシャードに属している場合。

Tip

欠落しているキー値は NULL 等価一致の一部として返されるため、NULL 値のキーが更新されないように、必要に応じて追加のクエリ条件(_id フィールドなど)を追加します。

以下も参照してください。

update分散トランザクション内で使用できます。

重要

ほとんどの場合、分散トランザクションでは 1 つのドキュメントの書き込み (write) よりもパフォーマンス コストが高くなります。分散トランザクションの可用性は、効果的なスキーマ設計の代わりにはなりません。多くのシナリオにおいて、非正規化されたデータモデル(埋め込みドキュメントと配列)が引き続きデータやユースケースに最適です。つまり、多くのシナリオにおいて、データを適切にモデリングすることで、分散トランザクションの必要性を最小限に抑えることができます。

トランザクションの使用に関するその他の考慮事項(ランタイム制限や oplog サイズ制限など)については、「本番環境での考慮事項」も参照してください。

トランザクションがクロスシャード間書き込みトランザクション(write transaction)でない場合に、分散トランザクション内にコレクションとインデックスを作成できます。

updateupsert: trueは、既存のコレクションまたは存在しないコレクションで実行できます。存在しないコレクションに対して実行すると、操作によってコレクションが作成されます。

Tip

以下も参照してください。

トランザクションで実行される場合、操作の書込み保証 (write concern)を明示的に設定しないでください。トランザクションで書込み保証を使用するには、「トランザクション書込み保証」を参照してください。

アップデート演算子を使用して、ドキュメントの指定されたフィールドのみを更新します。

たとえば、以下のドキュメントでmembersコレクションを作成する場合、

db.members.insertMany([
{ _id: 1, member: "abc123", status: "Pending", points: 0, misc1: "note to self: confirm status", misc2: "Need to activate" },
{ _id: 2, member: "xyz123", status: "D", points: 59, misc1: "reminder: ping me at 100pts", misc2: "Some random comment" },
])

次のコマンドは、 $setおよび$incアップデート演算子を使用して、 member"abc123"に等しいドキュメントのstatusフィールドとpointsフィールドを更新します。

db.runCommand(
{
update: "members",
updates: [
{
q: { member: "abc123" }, u: { $set: { status: "A" }, $inc: { points: 1 } }
}
],
ordered: false,
writeConcern: { w: "majority", wtimeout: 5000 }
}
)

<update>ドキュメントではオプションの multi フィールドが指定されていないため、q一致条件に一致するドキュメントが複数ある場合でも、更新によって変更されるのは 1 つのドキュメントのみです。

返されたドキュメントは、コマンドによって複数のドキュメントが見つかり、更新されたことを示しています。このコマンドは、次を返します。

{ "n" : 1, "nModified" : 1, "ok" : 1, <additional fields if run on a replica set/sharded cluster> }

詳細については「出力」を参照してください。

コマンドの実行後、コレクションには次のドキュメントが含まれます。

{ "_id" : 1, "member" : "abc123", "status" : "A", "points" : 1, "misc1" : "note to self: confirm status", "misc2" : "Need to activate" }
{ "_id" : 2, "member" : "xyz123", "status" : "D", "points" : 59, "misc1" : "reminder: ping me at 100pts", "misc2" : "Some random comment" }

アップデート演算子を使用して、ドキュメントの指定されたフィールドのみを更新し、アップデート演算子に true に設定された multi フィールドを含めます。

たとえば、コレクション members に次のドキュメントが含まれているとします。

{ "_id" : 1, "member" : "abc123", "status" : "A", "points" : 1, "misc1" : "note to self: confirm status", "misc2" : "Need to activate" }
{ "_id" : 2, "member" : "xyz123", "status" : "D", "points" : 59, "misc1" : "reminder: ping me at 100pts", "misc2" : "Some random comment" }

次のコマンドは、 $setおよび$incアップデート演算子を使用して、コレクション内の全ドキュメントの status フィールドと points フィールドをそれぞれ変更します。

db.runCommand(
{
update: "members",
updates: [
{ q: { }, u: { $set: { status: "A" }, $inc: { points: 1 } }, multi: true }
],
ordered: false,
writeConcern: { w: "majority", wtimeout: 5000 }
}
)

アップデートにより、q フィールドで指定されたクエリに一致するすべてのドキュメントが変更されます。これはつまり、コレクション内の全ドキュメントに一致する空のクエリです。

返されたドキュメントは、コマンドによって複数のドキュメントが見つかり、更新されたことを示しています。レプリカセットの場合、このコマンドは以下を返します。

{ "n" : 2, "nModified" : 2, "ok" : 1, <additional fields if run on a replica set/sharded cluster> }

詳細については「出力」を参照してください。

コマンドの実行後、コレクションには次のドキュメントが含まれます。

{ "_id" : 1, "member" : "abc123", "status" : "A", "points" : 2, "misc1" : "note to self: confirm status", "misc2" : "Need to activate" }
{ "_id" : 2, "member" : "xyz123", "status" : "A", "points" : 60, "misc1" : "reminder: ping me at 100pts", "misc2" : "Some random comment" }

updateコマンドは、更新に集計パイプラインを使用できます。 このパイプラインには次のステージが含まれる可能性があります。

集計パイプラインを使用すると、現在のフィールド値に基づいて条件付きのアップデートを表現したり、あるフィールドを他のフィールドの値を使用してアップデートするなど、より表現内容の多いアップデート ステートメントが可能になります。

次の例では、集計パイプラインを使用して、ドキュメント内の他のフィールドの値を使用してフィールドを変更します。

members コレクションには次の文書が含まれます。

{ "_id" : 1, "member" : "abc123", "status" : "A", "points" : 2, "misc1" : "note to self: confirm status", "misc2" : "Need to activate" }
{ "_id" : 2, "member" : "xyz123", "status" : "A", "points" : 60, "misc1" : "reminder: ping me at 100pts", "misc2" : "Some random comment" }

misc1 フィールドと misc2 フィールドを分けるのではなく、これらを新しい comments フィールドにまとめるとします。次のアップデート操作では、集計パイプラインを使用して新しい comments フィールドを追加し、コレクション内のすべてのドキュメントの misc1 フィールドと misc2 フィールドを削除します。

  • まず、status フィールドを "Modified" に設定し、他の 2 つのフィールド misc1 および misc2 の現在の内容が含まれる新しいフィールド comments を追加します。

  • 次に、misc1misc2 のフィールドを除きます。

db.runCommand(
{
update: "members",
updates: [
{
q: { },
u: [
{ $set: { status: "Modified", comments: [ "$misc1", "$misc2" ] } },
{ $unset: [ "misc1", "misc2" ] }
],
multi: true
}
],
ordered: false,
writeConcern: { w: "majority", wtimeout: 5000 }
}
)

注意

パイプライン内で使用される $set$unset は、集計ステージの$set$unset をそれぞれ示しており、アップデートの演算子の$set$unset ではありません。

返されたドキュメントは、コマンドによって複数のドキュメントが見つかり、更新されたことを示しています。このコマンドは、次を返します。

{ "n" : 2, "nModified" : 2, "ok" : 1, <additional fields if run on a replica set/sharded cluster> }

詳細については「出力」を参照してください。

コマンドの実行後、コレクションには次のドキュメントが含まれます。

{ "_id" : 1, "member" : "abc123", "status" : "Modified", "points" : 2, "comments" : [ "note to self: confirm status", "Need to activate" ] }
{ "_id" : 2, "member" : "xyz123", "status" : "Modified", "points" : 60, "comments" : [ "reminder: ping me at 100pts", "Some random comment" ] }

集計パイプラインを使用すると、現在のフィールド値に基づく条件付きアップデートを実行したり、アップデート時に別個のフィールド値の計算に現在のフィールド値を使用することができます。

db.students.insertMany( [
{ "_id" : 1, "tests" : [ 95, 92, 90 ] },
{ "_id" : 2, "tests" : [ 94, 88, 90 ] },
{ "_id" : 3, "tests" : [ 70, 75, 82 ] }
] );

集計パイプラインを使用すると、計算されたグレード平均およびレターグレードでドキュメントを更新することができます。

db.runCommand(
{
update: "students",
updates: [
{
q: { },
u: [
{ $set: { average : { $avg: "$tests" } } },
{ $set: { grade: { $switch: {
branches: [
{ case: { $gte: [ "$average", 90 ] }, then: "A" },
{ case: { $gte: [ "$average", 80 ] }, then: "B" },
{ case: { $gte: [ "$average", 70 ] }, then: "C" },
{ case: { $gte: [ "$average", 60 ] }, then: "D" }
],
default: "F"
} } } }
],
multi: true
}
],
ordered: false,
writeConcern: { w: "majority", wtimeout: 5000 }
}
)

注意

パイプラインで使用される$setは、アップデートオペレーターの $set ではなく、集計ステージ $setを参照します。

第 1 ステージ
$setステージでは、 testsフィールドの平均に基づいて新しいフィールドaverageを計算します。集計演算子 $avg の詳細については、$avg を参照してください。
第 2 ステージ
$setステージでは、前のステージで計算されたaverageフィールドに基づいて新しいフィールドgradeが計算されます。集計演算子 $switch の詳細については、$switch を参照してください。

返されたドキュメントは、コマンドによって複数のドキュメントが見つかり、更新されたことを示しています。このコマンドは、次を返します。

{ "n" : 3, "nModified" : 3, "ok" : 1, <additional fields if run on a replica set/sharded cluster> }

コマンドの実行後、コレクションには次のドキュメントが含まれます。

{ "_id" : 1, "tests" : [ 95, 92, 90 ], "average" : 92.33333333333333, "grade" : "A" }
{ "_id" : 2, "tests" : [ 94, 88, 90 ], "average" : 90.66666666666667, "grade" : "A" }
{ "_id" : 3, "tests" : [ 70, 75, 82 ], "average" : 75.66666666666667, "grade" : "C" }

次の例では、 members コレクションに対して複数のアップデート操作を実行します。

db.runCommand(
{
update: "members",
updates: [
{ q: { status: "P" }, u: { $set: { status: "D" } }, multi: true },
{ q: { _id: 5 }, u: { _id: 5, name: "abc123", status: "A" }, upsert: true }
],
ordered: false,
writeConcern: { w: "majority", wtimeout: 5000 }
}
)

返されたドキュメントは、コマンドが 10 ドキュメントを変更し、_id5 のドキュメントを挿入したことを示しています。詳細については「出力」を参照してください。

{
"ok" : 1,
"nModified" : 10,
"n" : 11,
"upserted" : [
{
"index" : 1,
"_id" : 5
}
]
}

照合を指定すると、大文字・小文字やアクセント記号など、文字列を比較するための言語独自のルールを指定できます。

コレクション myCollは、次のドキュメントを含みます。

{ _id: 1, category: "café", status: "A" }
{ _id: 2, category: "cafe", status: "a" }
{ _id: 3, category: "cafE", status: "a" }

次の操作には照合オプションが含まれます。

db.runCommand({
update: "myColl",
updates: [
{ q: { category: "cafe", status: "a" }, u: { $set: { status: "Updated" } }, collation: { locale: "fr", strength: 1 } }
]
})

配列フィールドを更新するときに、どの配列要素を更新するかを決定するためのarrayFiltersを指定できます。

次のドキュメントを使用してコレクション students を作成します。

db.students.insertMany( [
{ "_id" : 1, "grades" : [ 95, 92, 90 ] },
{ "_id" : 2, "grades" : [ 98, 100, 102 ] },
{ "_id" : 3, "grades" : [ 95, 110, 100 ] }
] );

grades 配列にある 100 以上の要素をすべて変更するには、次のように、フィルタリングした位置演算子 $[<identifier>]arrayFilters オプションを付けて使用します。

db.runCommand( {
update: "students",
updates: [
{ q: { grades: { $gte: 100 } }, u: { $set: { "grades.$[element]" : 100 } }, arrayFilters: [ { "element": { $gte: 100 } } ], multi: true}
]
} )

操作後、コレクションには次のドキュメントが含まれます。

{ "_id" : 1, "grades" : [ 95, 92, 90 ] }
{ "_id" : 2, "grades" : [ 98, 100, 100 ] }
{ "_id" : 3, "grades" : [ 95, 100, 100 ] }

次のドキュメントを使用してコレクション students2 を作成します。

db.students2.insertMany( [
{
"_id" : 1,
"grades" : [
{ "grade" : 80, "mean" : 75, "std" : 6 },
{ "grade" : 85, "mean" : 90, "std" : 4 },
{ "grade" : 85, "mean" : 85, "std" : 6 }
]
},
{
"_id" : 2,
"grades" : [
{ "grade" : 90, "mean" : 75, "std" : 6 },
{ "grade" : 87, "mean" : 90, "std" : 3 },
{ "grade" : 85, "mean" : 85, "std" : 4 }
]
}
] )

grades 配列のすべての要素のうち、グレードが 85 以上のもので mean フィールドの値を変更するには、フィルタリングされた位置演算子 $[<identifier>]arrayFilters とともに使用します。

db.runCommand({
update: "students2",
updates: [
{ q: { }, u: { $set: { "grades.$[elem].mean" : 100 } }, arrayFilters: [ { "elem.grade": { $gte: 85 } } ], multi: true }
]
})

操作後、コレクションには次のドキュメントが含まれます。

{
"_id" : 1,
"grades" : [
{ "grade" : 80, "mean" : 75, "std" : 6 },
{ "grade" : 85, "mean" : 100, "std" : 4 },
{ "grade" : 85, "mean" : 100, "std" : 6 }
]
}
{
"_id" : 2,
"grades" : [
{ "grade" : 90, "mean" : 100, "std" : 6 },
{ "grade" : 87, "mean" : 100, "std" : 3 },
{ "grade" : 85, "mean" : 100, "std" : 4 }
]
}

次のドキュメントを使用してサンプルmembers コレクションを作成します。

db.members.insertMany([
{ "_id" : 1, "member" : "abc123", "status" : "P", "points" : 0, "misc1" : null, "misc2" : null },
{ "_id" : 2, "member" : "xyz123", "status" : "A", "points" : 60, "misc1" : "reminder: ping me at 100pts", "misc2" : "Some random comment" },
{ "_id" : 3, "member" : "lmn123", "status" : "P", "points" : 0, "misc1" : null, "misc2" : null },
{ "_id" : 4, "member" : "pqr123", "status" : "D", "points" : 20, "misc1" : "Deactivated", "misc2" : null },
{ "_id" : 5, "member" : "ijk123", "status" : "P", "points" : 0, "misc1" : null, "misc2" : null },
{ "_id" : 6, "member" : "cde123", "status" : "A", "points" : 86, "misc1" : "reminder: ping me at 100pts", "misc2" : "Some random comment" }
])

コレクションに次のインデックスを作成します。

db.members.createIndex( { status: 1 } )
db.members.createIndex( { points: 1 } )

次の更新操作は、インデックス{ status: 1 }を使用することを明示的に示しています。

注意

存在しないインデックスを指定した場合、操作はエラーになります。

db.runCommand({
update: "members",
updates: [
{ q: { "points": { $lte: 20 }, "status": "P" }, u: { $set: { "misc1": "Need to activate" } }, hint: { status: 1 }, multi: true }
]
})

update コマンドは次を返します。

{ "n" : 3, "nModified" : 3, "ok" : 1 }

使用されたインデックスを確認するには、次の操作で explain を実行します。

db.runCommand(
{
explain: {
update: "members",
updates: [
{ q: { "points": { $lte: 20 }, "status": "P" }, u: { $set: { "misc1": "Need to activate" } }, hint: { status: 1 }, multi: true }
]
},
verbosity: "queryPlanner"
}
)

explainはドキュメントを変更しません。

バージョン 5.0 で追加

変数はletオプションまたはcフィールドで定義し、 updates配列でアクセスできます。

注意

変数を使用して結果をフィルタリングするには、$expr 演算子内の変数にアクセスする必要があります。

コレクション cakeFlavors を以下ように作成します。

db.cakeFlavors.insertMany( [
{ _id: 1, flavor: "chocolate" },
{ _id: 2, flavor: "strawberry" },
{ _id: 3, flavor: "cherry" }
] )

次の例では、lettargetFlavor 変数と newFlavor 変数を定義し、その変数を使用してケーキのフレーバーをチェリーからオレンジに変更します。

db.runCommand( {
update: db.cakeFlavors.getName(),
updates: [
{ q: { $expr: { $eq: [ "$flavor", "$$targetFlavor" ] } },
u: [ { $set: { flavor: "$$newFlavor" } } ] }
],
let : { targetFlavor: "cherry", newFlavor: "orange" }
} )

次の例では、ctargetFlavor 変数と newFlavor 変数を定義し、その変数を使用してケーキのフレーバーをチョコレートからバニラに変更します。

db.runCommand( {
update: db.cakeFlavors.getName(),
updates: [
{ q: { $expr: { $eq: [ "$flavor", "$$targetFlavor" ] } },
u: [ { $set: { flavor: "$$newFlavor" } } ],
c: { targetFlavor: "chocolate", newFlavor: "vanilla" } }
]
} )

返されるドキュメントには、次のフィールドのサブセットが含まれます。

update.ok

コマンドのステータスです。

update.n

updateコマンドはドキュメントアップデートの配列を受け入れます。その一部はアップサートになる場合があります。アップデートの場合、 n はアップデート対象として選択されたドキュメントの数です。アップサートの場合、挿入されたドキュメントの n1 になります。サーバーではすべてのアップデートとアップサートの n 値を足し、合計が update.n として返されます。

アップデート操作によってドキュメントに変更が生じない場合(例: $set式は値を現在の値にアップデートし、 nnModifiedより大きくなる可能性があります。

update.nModified

更新されたドキュメントの数。 フィールドの値を現在の値に設定するなど、アップデート操作によってドキュメントに変更が生じない場合、 nModifiednより小さくなる可能性があります。

注意

一致したドキュメントのサブセットが更新された場合、たとえば、更新によって一部のドキュメントがスキーマ検証に失敗する場合、update コマンドによって返される nModified の値は正確ではない可能性があります。

update.upserted

upsert: true による更新を通じて挿入された各ドキュメントの情報を含むドキュメントの配列。

各ドキュメントには、次の情報が含まれています。

update.upserted.index

upsert:true ステートメントに応じてアップデートを定義するupdates 配列内の整数。0 から始まるインデックスを使用します。

update.upserted._id

追加されたドキュメントの _id 値。

update.writeErrors

更新操作中に発生したエラーに関する情報を含むドキュメントの配列。 writeErrors配列には、エラーが発生した更新ステートメントごとにエラー ドキュメントが含まれています。

各エラー ドキュメントには以下のフィールドが含まれます。

update.writeErrors.index

updates 配列内のアップデート ステートメントを定義する整数。0 から始まるインデックスを使用します。

update.writeErrors.code

エラーを識別する整数値です。

update.writeErrors.errmsg

エラーの説明です。

update.writeConcernError

書込み保証 (write concern) に関連するエラーを説明するドキュメント。

バージョン7.1での変更: updatemongosで実行される場合、1 つ以上の書込みエラーが発生しても、書込み保証エラーが常に報告されます。

以前のリリースでは、書込みエラーが発生すると、 updateは書込み保証エラーを報告しないことがありました。

writeConcernErrorドキュメントには次のフィールドが含まれています。

update.writeConcernError.code

書込み保証 (write concern) エラーの原因を示す整数値です。

update.writeConcernError.errmsg

書込み保証 (write concern) エラーの原因の説明です。

update.writeConcernError.errInfo.writeConcern

対応する操作に使用される書込み保証 (write concern) オブジェクトです。書込み保証 (write concern) オブジェクト フィールドの詳細については、「書込み保証 (write concern) の仕様」を参照してください。

書込み保証 (write concern) オブジェクトには、書込み保証 (write concern) のソースを示す以下のフィールドも含むことができます。

update.writeConcernError.errInfo.writeConcern.provenance

書込み保証 (write concern) が発生した場所を示す文字列値です(書込み保証 (write concern) provenance と呼ばれます)。次の表は、このフィールドに指定できる値とその意味を示しています。

出所
説明
clientSupplied
書き込み保証(write concern)がアプリケーションで指定されました。
customDefault
書込み保証 (write concern) は、カスタム定義されたデフォルト値に基づきます。setDefaultRWConcern を参照してください。
getLastErrorDefaults
書込み保証 (write concern) は、レプリカセットの settings.getLastErrorDefaults のフィールドに基づきます。
implicitDefault
他の書き込み保証(write concern)が一切指定されていない状態で、サーバーから発生した書き込み保証。

前述のアップデート固有の戻りフィールドに加えて、 db.runCommand()には追加情報が含まれます。

  • レプリカ セットの場合、optimeelectionId$clusterTime 、およびoperationTime

  • シャーディングされたクラスターの場合、operationTimeおよび$clusterTime

これらのフィールドの詳細については db.runCommand レスポンスを参照してください。

以下は、アップサートを実行したupdateコマンドが成功した場合に返されるドキュメントの例です。

{
"ok" : 1,
"nModified" : 0,
"n" : 1,
"upserted" : [
{
"index" : 0,
"_id" : ObjectId("52ccb2118908ccd753d65882")
}
]
}

以下は、3 つのアップデートステートメントを含む一括アップデートで返されるドキュメントの例です。1 つのアップデートステートメントは成功し、他の 2 つのアップデートステートメントではエラーが発生しました。

{
"ok" : 1,
"nModified" : 1,
"n" : 1,
"writeErrors" : [
{
"index" : 1,
"code" : 16837,
"errmsg" : "The _id field cannot be changed from {_id: 1.0} to {_id: 5.0}."
},
{
"index" : 2,
"code" : 16837,
"errmsg" : "The _id field cannot be changed from {_id: 2.0} to {_id: 6.0}."
},
]
}

戻る

resetError