AI エージェント向け: ドキュメントインデックスは https://www.mongodb.com/ja-jp/docs/llms.txt で利用できます。すべてのページの markdown バージョンは、いずれかの URL パスに .md を追加することで利用できます。
Docs Menu

$merge(集計ステージ)

注意

このページでは、集計パイプラインの結果をコレクションに出力する$merge ステージについて説明します。複数のドキュメントを 1 つのドキュメントに結合する$mergeObjects演算子については、$mergeObjectsを参照してください。

$merge

集計パイプラインの結果を、指定したコレクションに書き込みます。$merge 演算子はパイプラインの最後ののステージでなければなりません。

$merge ステージでは、次のことができます。

  • 同じデータベースまたは異なるデータベース内のコレクションに出力できます。

  • Can output to the same collection that is being aggregated. For more information, see Output to the Same Collection that is Being Aggregated.

  • Consider the following points when using $merge or $out stages in an aggregation pipeline:

    • MongoDB 5.0 以降では、クラスター内のすべてのノードの featureCompatibilityVersion が 5.0 以上に設定されており、読み込み設定(read preference) でセカンダリ読み取りが許可されている場合、$merge ステージのパイプラインをレプリカセットのセカンダリノードで実行できます。

      • $merge $out ステージはセカンダリ ノードで実行されますが、書込み (write) 操作はプライマリ ノードに送信されます。

      • Not all driver versions support $merge operations sent to the secondary nodes. For details, see the driver documentation.

    • MongoDB の以前のバージョンでは、$out または $merge ステージを持つパイプラインは常にプライマリ ノードで実行され、読み込み設定 (read preference) は考慮されませんでした。

  • 出力コレクションがまだ存在しない場合は、新しいコレクションを作成します。

  • 結果(新しいドキュメントの挿入、ドキュメントのマージ、ドキュメントの置換、既存のドキュメントの保持、操作の失敗、カスタムアップデートパイプラインによるドキュメントの処理)を既存のコレクションに組み込むことができます。

  • シャーディングされたコレクションに出力できます。入力コレクションもシャーディング可能です。

For a comparison with the $out stage which also outputs the aggregation results to a collection, see $merge and $out Comparison.

注意

オンデマンドのマテリアライズドビュー

$merge は、コレクションの完全な置換を行うのではなく、パイプラインの結果を既存の出力コレクションに組み込むことができます。この機能により、ユーザーはオンデマンドのマテリアライズドビューを作成できます。ここでは、パイプラインの実行時に出力コレクションの内容が段階的に更新されます。

このユースケースの詳細については、このページの例だけでなく、オンデマンド マテリアライズドビューも参照してください。

マテリアライズドビューは読み取り専用のビューとは別物です。読み取り専用ビューの作成については、「読み取り専用ビュー」を参照してください。

次の環境でホストされる配置には $merge を使用できます。

  • MongoDB Atlas: The fully managed service for MongoDB deployments in the cloud
  • 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ステージは、次のフィールドを持つドキュメントを取得します。

フィールド
説明

出力コレクション。次のいずれかを指定します。

  • 集計が実行されるのと同じデータベース内のコレクションに出力する文字列としてのコレクション名。以下に例を示します。

    into: "myOutput"

  • 指定されたデータベース内のコレクションに出力するドキュメント内のデータベース名とコレクション名。以下に例を示します。

    into: { db:"myDB", coll:"myOutput" }

出力コレクションが存在しない場合、$merge はコレクションを作成します。

出力コレクションはシャーディングされたコレクションにすることができます。

任意。ドキュメントのユニークな識別子として機能するフィールド。識別子は、結果ドキュメントが出力コレクション内の既存のドキュメントと一致するかどうかを判断します。次のいずれかを指定します。

  • 文字列としての 1 つのフィールド名。以下に例を示します。

    on: "_id"

  • 配列内のフィールドの組み合わせ。以下に例を示します。

    on: [ "date", "customerId" ]

    配列内のフィールドの順序は重要ではなく、同じフィールドを複数回指定することはできません。

指定されたフィールドの場合、次のようになります。

  • 集計結果ドキュメントには、on フィールドが _id フィールドである場合を除き、on で指定されたフィールドが含まれている必要があります。結果ドキュメントに _id フィールドがない場合、MongoDB はそれを自動的に追加します。

  • For deployments running MongoDB 8.0 and earlier, specified field or fields for on cannot be missing or contain a null value. Starting in MongoDB 8.1, if the supporting index is not sparse, the specified field or fields for on can be missing or contain a null value.

  • 指定されたフィールドに配列値を含めることはできません。

$merge requires a unique index with keys that correspond to the on identifier fields. Although the order of the index key specification does not matter, the unique index must only contain the on fields as its keys.

  • また、インデックスが保持する照合は、集計が保持する照合と同じであることが必要です。

  • 一意なインデックスはスパース インデックスにできます。

  • 一意なインデックスを部分インデックスにすることはできません。

  • 既に存在する出力コレクションの場合、対応するインデックスが既に存在している必要があります。

オンのデフォルト値は出力コレクションによって異なります。

  • If the output collection does not exist, the on identifier must be and defaults to the _id field. The corresponding unique _id index is automatically created.

    • 存在しないコレクションに対して異なるオン識別子フィールドを使用するには、まず目的のフィールドにユニークインデックスを作成してコレクションを作成します。例えについては「存在しない出力コレクションのセクション」を参照してください。

    • MongoDB 8.3 以降では、サーバーは自動作成された _idインデックスがクエリの照合と一致することを確認します。照合が一致しない場合、_idインデックスはクエリの一意性を提供できず、クエリは実行されません。

  • 既存の出力コレクションがシャーディングされていない場合、on 識別子はデフォルトで _id フィールドになります。

  • If the existing output collection is a sharded collection, the on identifier defaults to all the shard key fields and the _id field. If specifying a different on identifier, the on must contain all the shard key fields.

Optional. The behavior of $merge if a result document and an existing document in the collection have the same value for the specified on field(s).

次のいずれかを指定できます。

  • 以下の事前定義されたアクション文字列の中から 1 つ。

    • "replace":

      Replace the existing document in the output collection with the matching results document.

      置換を実行する場合、置換ドキュメントによって _id 値やシャードキー値(出力コレクションがシャーディングされている場合)は変更されません。それ以外の場合、操作はエラーを生成します。

      To avoid this error, if the on field does not include the _id field, remove the _id field in the aggregation results to avoid the error, such as with a preceding $unset stage, and so on.

    • "keepExisting":

      既存のドキュメントを出力コレクションに保持します。

    • "merge" (Default):

      一致するドキュメントをマージします($mergeObjects 演算子と同様)。

      • 結果ドキュメントに既存のドキュメントにないフィールドが含まれている場合は、それらの新しいフィールドを既存のドキュメントに追加します。

      • 結果ドキュメントに既存のドキュメントのフィールドが含まれている場合は、既存のフィールド値を結果ドキュメントのフィールド値に置き換えます。

      たとえば、出力コレクションに以下のドキュメントがあるとします。

      { _id: 1, a: 1, b: 1 }

      また、集計結果には以下のドキュメントがあるとします。

      { _id: 1, b: 5, z: 1 }

      その場合、マージされたドキュメントは以下のようになります。

      { _id: 1, a: 1, b: 5, z: 1 }

      マージを実行する場合、マージされたドキュメントによって _id 値やシャードキー値(出力コレクションがシャーディングされている場合)は変更されません。それ以外の場合、操作はエラーを生成します。

      To avoid this error, if the on field does not include the _id field, remove the _id field in the aggregation results to avoid the error, such as with a preceding $unset stage, and so on.

    • "fail":

      集計操作を停止して失敗させます。前ドキュメントからの出力コレクションへの変更は、元には戻されません。

  • コレクション内のドキュメントを更新するための集計パイプライン。

    [ <stage1>, <stage2> ... ]

    パイプラインは、次のステージのみで構成できます。

    The pipeline cannot modify the on field's value. For example, if you are matching on the field month, the pipeline cannot modify the month field.

    whenMatched pipeline は、$<field> を使用して出力コレクション内の既存のドキュメントのフィールドに直接アクセスできます。

    集計結果ドキュメントのフィールドにアクセスするには、次のいずれかを使用します。

    • The built-in $$new variable to access the field. Specifically, $$new.<field>. The $$new variable is only available if the let specification is omitted.

    • The user-defined variables in the let field.

      二重ドル記号($$)プレフィックスと変数名を $$<variable_name> 形式で指定します。たとえば、$$year のような形式です。変数がドキュメントに設定されている場合は、$$<variable_name>.<field> という形式でフィールドを含めることもできます。たとえば、$$year.month のような形式です。

      その他の例については、 「変数を使用してマージをカスタマイズする」を参照してください。

Optional. Specifies variables for use in the whenMatched pipeline.

以下のように、変数名と値の式を使ってドキュメントを指定します。

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

If unspecified, defaults to { new: "$$ROOT" } (see ROOT). The whenMatched pipeline can access the $$new variable.

To access the variables in the whenMatched pipeline:

二重ドル記号($$)プレフィックスと変数名を $$<variable_name> 形式で指定します。たとえば、$$year のような形式です。変数がドキュメントに設定されている場合は、$$<variable_name>.<field> という形式でフィールドを含めることもできます。たとえば、$$year.month のような形式です。

For examples, see Use Variables to Customize the Merge.

任意。結果ドキュメントがアウトコレクション内の既存のドキュメントと一致しない場合の $merge の動作。

以下の事前定義されたアクション文字列のいずれかを指定できます。

  • "insert" (Default):

    ドキュメントを出力コレクションに挿入します。

  • "discard":

    ドキュメントを破棄します。具体的には、$merge はドキュメントを出力コレクションに挿入しません。

  • "fail":

    集計操作を停止して失敗させます。すでに出力コレクションに書き込まれた変更は、元には戻されません。

集計パイプライン結果のドキュメントに _id フィールドが存在しない場合は、$merge ステージによって自動的にフィールドが生成されます。

たとえば、次の集計パイプラインでは、$project は$merge に渡されるドキュメントから_id フィールドを除外します。$merge がこれらのドキュメントを "newCollection" に書き込むと、$merge は新しい_id フィールドと値を生成します。

db.movies.aggregate( [
{ $project: { _id: 0 } },
{ $merge : { into : "newCollection" } }
] )

指定された出力コレクションが存在しない場合は、$merge操作によって新しいコレクションが作成されます。

  • 出力コレクションは、$merge が最初のドキュメントをコレクションに書込んだときに作成され、すぐに表示されます。

  • 集計が失敗した場合、エラーの前に $merge によって完了した書き込みはロールバックされません。

注意

レプリカセットまたはスタンドアロンでは、出力データベースが存在しない場合、$merge によってデータベースも作成されます。

シャーディングされたクラスターの場合、指定された出力データベースがすでに存在している必要があります。

If the output collection does not exist, $merge requires the on identifier to be the _id field. To use a different on field value for a collection that does not exist, you can create the collection first by creating a unique index on the desired field(s) first. For example, if the output collection newDailyCommentCount does not exist and you want to specify the commentDate field as the on identifier:

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" } }
] )

The $merge stage can output to a sharded collection. When the output collection is sharded, $merge uses the _id field and all the shard key fields as the default on identifier. If you override the default, the on identifier must include all the shard key fields:

{ $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
);

The moviesByYearAndRating collection will contain documents with movie statistics by year (year field) and content rating (shard key); specifically, the on identifier is ["year", "rated"] (the ordering of the fields does not matter). Because $merge requires a unique index with keys that correspond to the on identifier fields, create the unique index (the ordering of the fields do not matter): [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]

sh.shardCollection() メソッドは、シャードキーが範囲ベースであり、コレクションが空であり、シャードキーにユニークインデックスがまだ存在しない場合に、{ unique: true } オプションを渡すとシャードキーにユニークインデックスを作成することもできます。

前の例では、on 識別子がシャードキーであり、さらに別のフィールドでもあるため、対応するインデックスを作成する別の操作が必要です。

$merge can replace an existing document in the output collection if the aggregation results contain a document or documents that match based on the on specification. As such, $merge can replace all documents in the existing collection if the aggregation results include matching documents for all existing documents in the collection and you specify "replace" for whenMatched.

ただし、集計結果に関係なく既存のコレクションを置き換えるには、代わりに $out を使用します。

$mergeによって既存のドキュメントの _id 値が変更されると、$merge エラーが発生します。

Tip

To avoid this error, if the on field does not include the _id field, remove the _id field in the aggregation results to avoid the error, such as with a preceding $unset stage, and so on.

さらに、シャーディングされたコレクションの場合、既存のドキュメントのシャードキー値が変更されると、$merge はエラーも生成します。

エラーが発生する前に $merge によって完了した書き込みはロールバックされません。

If the unique index used by $merge for on field(s) is dropped mid-aggregation, there is no guarantee that the aggregation will be killed. If the aggregation continues, there is no guarantee that documents do not have duplicate on field values.

$merge が出力コレクションの一意のインデックスに違反するドキュメントを書込もうとした場合、操作でエラーが生成されます。例:

コレクションでスキーマ検証が使用されており、 validationActionがerrorに設定されている場合、無効なドキュメントを挿入したり、 $mergeを使用して無効な値を持つドキュメントを更新したりすると、 MongoServerErrorがスローされ、ドキュメントはターゲット コレクションに書き込まれません。 無効なドキュメントが複数ある場合、最初に見つかった無効なドキュメントのみがエラーをスローします。 すべての有効なドキュメントはターゲット コレクションに書き込まれ、すべての無効なドキュメントは書込みに失敗します。

$merge 次のすべてが真である場合、ドキュメントを出力コレクションに直接挿入します。

  • The value of whenMatched is an aggregation pipeline.

  • The value of whenNotMatched is insert.

  • 出力コレクションに一致するドキュメントがありません。

$merge の導入により、MongoDB は集計パイプラインの結果をコレクションに書き込むための 2 つのステージ $merge と $out を提供します。

$merge
  • 同じデータベースまたは異なるデータベース内のコレクションに出力できます。
  • 同じデータベースまたは異なるデータベース内のコレクションに出力できます。
  • 出力コレクションがまだ存在しない場合は、新しいコレクションを作成します。
  • 出力コレクションがまだ存在しない場合は、新しいコレクションを作成します。
  • 結果(新しいドキュメントの挿入、ドキュメントのマージ、ドキュメントの置換、既存のドキュメントの保持、操作の失敗、カスタムアップデートパイプラインによるドキュメントの処理)を既存のコレクションに組み込むことができます。

    See also Replace Documents ($merge) vs Replace Collection ($out).

  • 出力コレクションが既に存在する場合は、完全に置き換えます。
  • シャーディングされたコレクションに出力できます。入力コレクションもシャーディング可能です。
  • シャーディングされたコレクションに出力できません。ただし、入力コレクションはシャーディングできます。
  • 以下の SQL ステートメントに対応します。

    • MERGE.

    • INSERT INTO T2 SELECT FROM T1.

    • SELECT INTO T2 FROM T1.

    • マテリアライズドビューの作成と更新。

  • 以下の SQL ステートメントに対応します。

    • INSERT INTO T2 SELECT FROM T1.

    • SELECT INTO T2 FROM T1.

警告

$mergeが集約されている同じコレクションに出力する場合、ドキュメントが複数回更新されたり、操作によって無限ループが発生したりする可能性があります。この動作は、$merge によって実行されるアップデートによって、ディスクに保存されているドキュメントの物理的な場所が変更された場合に発生します。ドキュメントの物理的な場所が変更されると、$merge はそのドキュメントを完全に新しいドキュメントとして表示し、追加のアップデートが行われる可能性があります。この動作の詳細については、「 日付の問題 」を参照してください。

$merge can output to the same collection that is being aggregated. You can also output to a collection which appears in other stages of the pipeline, such as $lookup.

制限事項
説明

集約パイプラインでは、トランザクション内で $merge を使用できません。

集計パイプラインでは、$merge を使用して時系列コレクションに出力することはできません。

ビュー定義
マテリアライズドビューとは別

ビュー定義に $merge ステージを含めることはできません。ビュー定義に入れ子パイプラインが含まれている場合(たとえば、ビュー定義に $facet ステージが含まれている場合)、この $merge ステージの制限は入れ子パイプラインにも適用されます。

$lookup ステージ

$lookup ステージのネストされたパイプラインに $merge ステージを含めることはできません。

$facet ステージ

$facet ステージのネストされたパイプラインに $merge ステージを含めることはできません。

$unionWith ステージ

$unionWith ステージのネストされたパイプラインに $merge ステージを含めることはできません。

"linearizable" 読み取り保証 (read concern)

The $merge stage cannot be used in conjunction with read concern "linearizable". That is, if you specify "linearizable" read concern for db.collection.aggregate(), you cannot include the $merge stage in the pipeline.