定義
注意
このページでは、集計パイプラインの結果をコレクションに出力する$merge ステージについて説明します。複数のドキュメントを 1 つのドキュメントに結合する$mergeObjects演算子については、$mergeObjectsを参照してください。
$merge集計パイプラインの結果を、指定したコレクションに書き込みます。
$merge演算子はパイプラインの最後ののステージでなければなりません。$mergeステージでは、次のことができます。同じデータベースまたは異なるデータベース内のコレクションに出力できます。
集約されている同じコレクションに出力できます。 詳細については、 「 集計されているのと同じコレクションへの出力 」を参照してください。
集計パイプラインで
$mergeまたは$outステージを使用する場合は、次の点を考慮してください。MongoDB 5.0 以降では、クラスター内のすべてのノードの featureCompatibilityVersion が
5.0以上に設定されており、読み込み設定(read preference) でセカンダリ読み取りが許可されている場合、$mergeステージのパイプラインをレプリカセットのセカンダリノードで実行できます。MongoDB の以前のバージョンでは、
$outまたは$mergeステージを持つパイプラインは常にプライマリ ノードで実行され、読み込み設定 (read preference) は考慮されませんでした。
出力コレクションがまだ存在しない場合は、新しいコレクションを作成します。
結果(新しいドキュメントの挿入、ドキュメントのマージ、ドキュメントの置換、既存のドキュメントの保持、操作の失敗、カスタムアップデートパイプラインによるドキュメントの処理)を既存のコレクションに組み込むことができます。
シャーディングされたコレクションに出力できます。入力コレクションもシャーディング可能です。
集計結果もコレクションに出力する
$outステージとの比較については、「$mergeと$outの比較 」を参照してください。
注意
オンデマンドのマテリアライズドビュー
$merge は、コレクションの完全な置換を行うのではなく、パイプラインの結果を既存の出力コレクションに組み込むことができます。この機能により、ユーザーはオンデマンドのマテリアライズドビューを作成できます。ここでは、パイプラインの実行時に出力コレクションの内容が段階的に更新されます。
このユースケースの詳細については、このページの例だけでなく、オンデマンド マテリアライズドビューも参照してください。
マテリアライズドビューは読み取り専用のビューとは別物です。読み取り専用ビューの作成については、「読み取り専用ビュー」を参照してください。
互換性
次の環境でホストされる配置には $merge を使用できます。
- MongoDB Atlas はクラウドでの MongoDB 配置のためのフルマネージド サービスです
MongoDB Enterprise: サブスクリプションベースの自己管理型 MongoDB バージョン
MongoDB Community: ソースが利用可能で、無料で使用できる自己管理型の MongoDB のバージョン
構文
$merge の構文は次のとおりです。
{ $merge: { into: <collection> -or- { db: <db>, coll: <collection> }, on: <identifier field> -or- [ <identifier field1>, ...], // Optional let: <variables>, // Optional whenMatched: <replace|keepExisting|merge|fail|pipeline>, // Optional whenNotMatched: <insert|discard|fail> // Optional} }以下に例を挙げます。
{ $merge: { into: "myOutput", on: "_id", whenMatched: "replace", whenNotMatched: "insert" } }同じデータベース内のコレクションへの書き込みを含め、$merge のすべてのデフォルト オプションを使用する場合は、簡略化された形式を使用できます。
{ $merge: <collection> } // Output collection is in the same database$mergeステージは、次のフィールドを持つドキュメントを取得します。
フィールド | 説明 |
|---|---|
出力コレクション。次のいずれかを指定します。
出力コレクションが存在しない場合、
出力コレクションはシャーディングされたコレクションにすることができます。 | |
任意。ドキュメントのユニークな識別子として機能するフィールド。識別子は、結果ドキュメントが出力コレクション内の既存のドキュメントと一致するかどうかを判断します。次のいずれかを指定します。
指定されたフィールドの場合、次のようになります。
オンのデフォルト値は出力コレクションによって異なります。
| |
任意.結果ドキュメントとコレクション内の既存のドキュメントで指定されたオン フィールドの値が同じ場合の 次のいずれかを指定できます。
| |
任意。 whenMatched パイプライン で使用する変数を指定します。 以下のように、変数名と値の式を使ってドキュメントを指定します。 指定されていない場合は、デフォルトで whenMatched パイプライン内の変数にアクセスするには、次のようにします。 二重ドル記号($$)プレフィックスと変数名を 例については、「変数を使用したマージのカスタマイズ 」を参照してください。 | |
任意。結果ドキュメントがアウトコレクション内の既存のドキュメントと一致しない場合の 以下の事前定義されたアクション文字列のいずれかを指定できます。
|
Considerations
_id フィールド生成
集計パイプライン結果のドキュメントに _id フィールドが存在しない場合は、$merge ステージによって自動的にフィールドが生成されます。
たとえば、次の集計パイプラインでは、$project は$merge に渡されるドキュメントから_id フィールドを除外します。$merge がこれらのドキュメントを "newCollection" に書き込むと、$merge は新しい_id フィールドと値を生成します。
db.movies.aggregate( [ { $project: { _id: 0 } }, { $merge : { into : "newCollection" } }] )出力コレクションが存在しない場合の新しいコレクションの作成
指定された出力コレクションが存在しない場合は、$merge操作によって新しいコレクションが作成されます。
出力コレクションは、
$mergeが最初のドキュメントをコレクションに書込んだときに作成され、すぐに表示されます。集計が失敗した場合、エラーの前に
$mergeによって完了した書き込みはロールバックされません。
注意
レプリカセットまたはスタンドアロンでは、出力データベースが存在しない場合、$merge によってデータベースも作成されます。
シャーディングされたクラスターの場合、指定された出力データベースがすでに存在している必要があります。
出力コレクションが存在しない場合、$mergeではオン識別子が _id フィールドである必要があります。存在しないコレクションに対して別の on フィールド値を使用するには、まず目的のフィールドに一意なインデックスを作成してコレクションを作成します。たとえば、出力コレクション newDailyCommentCount が存在せず、オン識別子としてcommentDate フィールドを指定する場合は次のようになります。
db.newDailyCommentCount.createIndex( { commentDate: 1 }, { unique: true } )
db.comments.aggregate( [ { $match: { date: { $gte: new Date("2002-01-01"), $lt: new Date("2002-02-01") } } }, { $group: { _id: { $dateToString: { format: "%Y-%m-%d", date: "$date" } }, count: { $sum: 1 } } }, { $project: { _id: 0, commentDate: { $toDate: "$_id" }, count: 1 } }, { $merge : { into : "newDailyCommentCount", on: "commentDate" } }] )シャーディングされたコレクションへの出力
$merge ステージはシャーディングされたコレクションに出力できます。出力コレクションがシャーディングされた場合、$merge は_id フィールドとすべてのシャードキー フィールドをデフォルトのオン識別子として使用します。デフォルトを上書きする場合、オン識別子にすべてのシャードキー フィールドを含める必要があります。
{ $merge: { into: "<shardedColl>" or { db:"<sharding enabled db>", coll: "<shardedColl>" }, on: [ "<shardkeyfield1>", "<shardkeyfield2>",... ], // Shard key fields and any additional fields let: <variables>, // Optional whenMatched: <replace|keepExisting|merge|fail|pipeline>, // Optional whenNotMatched: <insert|discard|fail> // Optional} }たとえば、sh.shardCollection() メソッドを使用して、rated フィールドをシャードキーとして持つ新しいシャーディングされたコレクションmoviesByYearAndRating を作成します。
sh.shardCollection( "sample_mflix.moviesByYearAndRating", // Namespace of the collection to shard { rated: 1 }, // Shard key);moviesByYearAndRatingコレクションには、年(year フィールド)とコンテンツレーティング(シャードキー)ごとの映画統計情報を含むドキュメントが格納されます。具体的には、オン識別子は ["year", "rated"] です(フィールドの順序は関係ありません)。$mergeには、オン識別子フィールドに対応するキーを持つユニークインデックスが必要なので、ユニークインデックスを作成します(フィールドの順序は関係ありません)。[1]
db.moviesByYearAndRating.createIndex( { rated: 1, year: 1 }, { unique: true } )シャーディングされたコレクション moviesByYearAndRating と一意のインデックスを作成すると、$merge を使用して集計結果をこのコレクションに出力でき、この例のように [ "year", "rated" ] に一致します。
db.movies.aggregate( [ { $match: { rated: { $ne: null }, year: { $ne: null } } }, { $group: { _id: { year: "$year", rated: "$rated" }, movieCount: { $sum: 1 } } }, { $project: { _id: 0, year: "$_id.year", rated: "$_id.rated", movieCount: 1 } }, { $merge: { into: "moviesByYearAndRating", "on": [ "year", "rated" ], whenMatched: "replace", whenNotMatched: "insert" } }] )| [1] |
前の例では、 |
ドキュメントの置換($merge)とコレクションの置換($out)
$merge は、集計結果にオンの指定に基づいて一致するドキュメントが含まれている場合、出力先コレクション内の既存のドキュメントを置き換えることができます。そのため、集約結果にコレクション内のすべての既存ドキュメントと一致するドキュメントが含まれており、かつ「replace」 を whenMatched に対して指定した場合、$merge は既存のコレクション内のすべてのドキュメントを置き換えることができます。
ただし、集計結果に関係なく既存のコレクションを置き換えるには、代わりに $out を使用します。
既存のドキュメント、_id、およびシャードキー値
$mergeによって既存のドキュメントの _id 値が変更されると、$merge エラーが発生します。
ユニークインデックス制約
$merge がオンフィールドに使用する一意のインデックスが集計の途中で削除された場合、集計が強制終了される保証はありません。集計が続行される場合、ドキュメントに重複する on フィールド値が存在しないという保証はありません。
$merge が出力コレクションの一意のインデックスに違反するドキュメントを書込もうとした場合、操作でエラーが生成されます。例:
オン フィールドのインデックス以外の一意のインデックスに違反する、一致しないドキュメントを挿入します。
オン フィールドのインデックス以外の一意のインデックスに違反するドキュメントとなる一致するドキュメントをマージします。
スキーマ検証
コレクションでスキーマ検証が使用されており、 validationActionがerrorに設定されている場合、無効なドキュメントを挿入したり、 $mergeを使用して無効な値を持つドキュメントを更新したりすると、 MongoServerErrorがスローされ、ドキュメントはターゲット コレクションに書き込まれません。 無効なドキュメントが複数ある場合、最初に見つかった無効なドキュメントのみがエラーをスローします。 すべての有効なドキュメントはターゲット コレクションに書き込まれ、すべての無効なドキュメントは書込みに失敗します。
whenMatched パイプラインの動作
$merge 次のすべてが真である場合、ドキュメントを出力コレクションに直接挿入します。
whenMatchedの値は集計パイプラインです。
whenNotMatched の値は
insertです。出力コレクションに一致するドキュメントがありません。
$merge と $out の比較
$merge の導入により、MongoDB は集計パイプラインの結果をコレクションに書き込むための 2 つのステージ $merge と $out を提供します。
$merge | |
|---|---|
|
|
|
|
|
|
|
|
|
|
集計されているのと同じコレクションへの出力
警告
$merge の出力が集約されている同じコレクションに出力される場合、ドキュメントが複数回更新されたり、操作によって無限ループが発生したりする可能性があります。この動作は、$merge によって実行されるアップデートによって、ディスクに保存されているドキュメントの物理的な場所が変更された場合に発生します。ドキュメントの物理的な場所が変更されると、$merge はそのドキュメントを完全に新しいドキュメントとして表示し、追加のアップデートが行われることがあります。この動作の詳細については、日付の問題を参照してください。
$merge は、集約されている同じコレクションに出力できます。$lookupなど、パイプラインの他のステージに表示されるコレクションに出力することもできます。
制限事項
制限事項 | 説明 |
|---|---|
集約パイプラインでは、トランザクション内で | |
集計パイプラインでは、 | |
ビュー定義 | ビュー定義に |
|
|
|
|
|
|
|
|