> For the complete MongoDB documentation index, see www.mongodb.com/docs/llms.txt

# $merge (aggregation stage)

## Definition

**Note:**

This page describes the `$merge` stage, which outputs the aggregation pipeline results to a collection. For the [`$mergeObjects`](https://www.mongodb.com/docs/manual/reference/expression/mergeobjects.md#mongodb-expression-exp.-mergeObjects) operator, which merges documents into a single document, see [`$mergeObjects`.](https://www.mongodb.com/docs/manual/reference/expression/mergeobjects.md#mongodb-expression-exp.-mergeObjects)

Writes the results of the [aggregation pipeline](https://www.mongodb.com/docs/manual/core/aggregation-pipeline.md#std-label-aggregation-pipeline) to a specified collection. The `$merge` operator must be the **last** stage in the pipeline.

The `$merge` stage:

- Can output to a collection in the same or different database.

- Can output to the same collection that is being aggregated. For more information, see [Output to the Same Collection that is Being Aggregated.](https://www.mongodb.com/docs/manual/reference/operator/aggregation/merge.md#std-label-merge-behavior-same-collection)

- Consider the following points when using [`$merge`](https://www.mongodb.com/docs/manual/reference/operator/aggregation/merge.md#mongodb-pipeline-pipe.-merge) or [`$out`](https://www.mongodb.com/docs/manual/reference/operator/aggregation/out.md#mongodb-pipeline-pipe.-out) stages in an [aggregation pipeline:](https://www.mongodb.com/docs/manual/core/aggregation-pipeline.md#std-label-aggregation-pipeline)
  - Starting in MongoDB 5.0, pipelines with a `$merge` stage can run on replica set [secondary](https://www.mongodb.com/docs/manual/reference/glossary.md#std-term-secondary) nodes if all the nodes in the cluster have the [featureCompatibilityVersion](https://www.mongodb.com/docs/manual/reference/command/setfeaturecompatibilityversion.md#std-label-view-fcv) set to `5.0` or higher and the [read preference](https://www.mongodb.com/docs/manual/core/read-preference.md#std-label-read-preference) allows secondary reads.

    - `$merge` and `$out` stages run on secondary nodes, but write operations are sent to the [primary](https://www.mongodb.com/docs/manual/reference/glossary.md#std-term-primary) node.

    - Not all driver versions support `$merge` operations sent to the secondary nodes. For details, see the [driver](https://www.mongodb.com/docs/drivers/) documentation.

  - In earlier MongoDB versions, pipelines with `$out` or `$merge` stages always run on the primary node and read preference isn't considered.

- Creates a new collection if the output collection does not already exist.

- Can incorporate results (insert new documents, merge documents, replace documents, keep existing documents, fail the operation, process documents with a custom update pipeline) into an existing collection.

- Can output to a sharded collection. Input collection can also be sharded.

For a comparison with the [`$out`](https://www.mongodb.com/docs/manual/reference/operator/aggregation/out.md#mongodb-pipeline-pipe.-out) stage which also outputs the aggregation results to a collection, see [`$merge` and `$out` Comparison.](https://www.mongodb.com/docs/manual/reference/operator/aggregation/merge.md#std-label-merge-out-comparison)

**Note: On-Demand Materialized Views**

`$merge` can incorporate the pipeline results into an existing output collection rather than perform a full replacement of the collection. This functionality allows users to create on-demand materialized views, where the content of the output collection is incrementally updated when the pipeline is run.

For more information on this use case, see [On-Demand Materialized Views](https://www.mongodb.com/docs/manual/core/materialized-views.md) as well as the examples on this page.

Materialized views are separate from read-only views. For information on creating read-only views, see [read-only views.](https://www.mongodb.com/docs/manual/core/views.md)

## Compatibility

You can use `$merge` for deployments hosted in the following environments:

- [MongoDB Atlas](https://www.mongodb.com/docs/atlas): The fully managed service for MongoDB deployments in the cloud

* [MongoDB Enterprise](https://www.mongodb.com/docs/manual/administration/install-enterprise.md#std-label-install-mdb-enterprise): The subscription-based, self-managed version of MongoDB

* [MongoDB Community](https://www.mongodb.com/docs/manual/administration/install-community.md#std-label-install-mdb-community-edition): The source-available, free-to-use, and self-managed version of MongoDB

## Syntax

`$merge` has the following syntax:

```javascript
{ $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
} }
```

For example:

```javascript
{ $merge: { into: "myOutput", on: "_id", whenMatched: "replace", whenNotMatched: "insert" } }
```

If using all default options for `$merge`, including writing to a collection in the same database, you can use the simplified form:

```javascript
{ $merge: <collection> } // Output collection is in the same database
```

The `$merge` stage takes a document with the following fields:

| Field | Description |
| --- | --- |
| [into](https://www.mongodb.com/docs/manual/reference/operator/aggregation/merge.md#std-label-merge-into) | The output collection. Specify either: The collection name as a string to output to a collection in the same database where the aggregation is run. For example:`into: "myOutput"`; The database and collection name in a document to output to a collection in the specified database. For example:`into: { db:"myDB", coll:"myOutput" }` If the output collection does not exist, `$merge` creates the collection: For a [replica set](https://www.mongodb.com/docs/manual/replication.md#std-label-replica-set) or a standalone, if the output database does not exist, `$merge` also creates the database.; For a [sharded cluster](https://www.mongodb.com/docs/manual/sharding.md#std-label-sharded-cluster), the specified output database must already exist. The output collection can be a sharded collection. |
| [on](https://www.mongodb.com/docs/manual/reference/operator/aggregation/merge.md#std-label-merge-on) | Optional. Field or fields that act as a unique identifier for a document. The identifier determines if a results document [matches](https://www.mongodb.com/docs/manual/reference/operator/aggregation/merge.md#std-label-merge-whenMatched) an existing document in the output collection. Specify either: A single field name as a string. For example:`on: "_id"`; A combination of fields in an array. For example:`on: [ "date", "customerId" ]`The order of the fields in the array does not matter, and you cannot specify the same field multiple times. For the specified field or fields: The aggregation results documents must contain the field(s) specified in the `on`, unless the `on` field is the `_id` field. If the `_id` field is missing from a results document, MongoDB adds it automatically.; 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](https://www.mongodb.com/docs/manual/reference/operator/aggregation/merge.md#std-label-merge-on-supporting-index) is not sparse, the specified field or fields for `on` can be missing or contain a null value.; The specified field or fields cannot contain an array value. `$merge` requires a [unique](https://www.mongodb.com/docs/manual/core/index-unique.md#std-label-index-type-unique) index with keys that correspond to the [on](https://www.mongodb.com/docs/manual/reference/operator/aggregation/merge.md#std-label-merge-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. The index must also have the same [collation](https://www.mongodb.com/docs/manual/reference/collation.md#std-label-collation) as the aggregation's collation.; The unique index can be a [sparse](https://www.mongodb.com/docs/manual/core/index-sparse.md#std-label-index-type-sparse) index.; The unique index cannot be a [partial](https://www.mongodb.com/docs/manual/core/index-partial.md#std-label-index-type-partial) index.; For output collections that already exist, the corresponding index must already exist. The default value for [on](https://www.mongodb.com/docs/manual/reference/operator/aggregation/merge.md#std-label-merge-on) depends on the output collection: If the output collection does not exist, the [on](https://www.mongodb.com/docs/manual/reference/operator/aggregation/merge.md#std-label-merge-on) identifier must be and defaults to the `_id` field. The corresponding unique `_id` index is automatically created.To use a different [on](https://www.mongodb.com/docs/manual/reference/operator/aggregation/merge.md#std-label-merge-on) identifier field(s) for a collection that does not exist, you can create the collection first by creating a unique index on the desired field(s). See the [section on non-existent output collection](https://www.mongodb.com/docs/manual/reference/operator/aggregation/merge.md#std-label-merge-use-different-on) for an example.; Starting in MongoDB 8.3, the server checks to ensure that the automatically created `_id` index matches the query's collation. If the collations do not match, the `_id` index cannot provide uniqueness for the query, and the query will not run.; If the existing output collection is unsharded, the `on` identifier defaults to the `_id` field.; If the existing output collection is a sharded collection, the [on](https://www.mongodb.com/docs/manual/reference/operator/aggregation/merge.md#std-label-merge-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. |
| [whenMatched](https://www.mongodb.com/docs/manual/reference/operator/aggregation/merge.md#std-label-merge-whenMatched) | Optional. The behavior of `$merge` if a result document and an existing document in the collection have the same value for the specified [on](https://www.mongodb.com/docs/manual/reference/operator/aggregation/merge.md#std-label-merge-on) field(s). You can specify either: One of the pre-defined action strings:["replace":](https://www.mongodb.com/docs/manual/reference/operator/aggregation/merge.md#std-label-merge-whenMatched-replace)Replace the existing document in the [output collection](https://www.mongodb.com/docs/manual/reference/operator/aggregation/merge.md#std-label-merge-into) with the matching results document.When performing a replace, the replacement document cannot result in a modification of the `_id` value or, if the output collection is sharded, the shard key value. Otherwise, the operation generates an error.To avoid this error, if the [on](https://www.mongodb.com/docs/manual/reference/operator/aggregation/merge.md#std-label-merge-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`](https://www.mongodb.com/docs/manual/reference/operator/aggregation/unset.md#mongodb-pipeline-pipe.-unset) stage, and so on.; ["keepExisting":](https://www.mongodb.com/docs/manual/reference/operator/aggregation/merge.md#std-label-merge-whenMatched-keepExisting)Keep the existing document in the [output collection.](https://www.mongodb.com/docs/manual/reference/operator/aggregation/merge.md#std-label-merge-into); ["merge"](https://www.mongodb.com/docs/manual/reference/operator/aggregation/merge.md#std-label-merge-whenMatched-merge) (Default):Merge the matching documents (similar to the [`$mergeObjects`](https://www.mongodb.com/docs/manual/reference/expression/mergeobjects.md#mongodb-expression-exp.-mergeObjects) operator).If the results document contains fields not in the existing document, add these new fields to the existing document.; If the results document contains fields in the existing document, replace the existing field values with those from the results document.For example, if the output collection has the document:`{ _id: 1, a: 1, b: 1 }`And the aggregation results has the document:`{ _id: 1, b: 5, z: 1 }`Then, the merged document is:`{ _id: 1, a: 1, b: 5, z: 1 }`When performing a merge, the merged document cannot result in a modification of the `_id` value or, if the output collection is sharded, the shard key value. Otherwise, the operation generates an error.To avoid this error, if the [on](https://www.mongodb.com/docs/manual/reference/operator/aggregation/merge.md#std-label-merge-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`](https://www.mongodb.com/docs/manual/reference/operator/aggregation/unset.md#mongodb-pipeline-pipe.-unset) stage, and so on.; ["fail":](https://www.mongodb.com/docs/manual/reference/operator/aggregation/merge.md#std-label-merge-whenMatched-fail)Stop and fail the aggregation operation. Any changes to the output collection from previous documents are not reverted.; An aggregation pipeline to update the document in the collection.`[ <stage1>, <stage2> ... ]`The pipeline can only consist of the following stages:[`$addFields`](https://www.mongodb.com/docs/manual/reference/operator/aggregation/addfields.md#mongodb-pipeline-pipe.-addFields) and its alias [`$set`](https://www.mongodb.com/docs/manual/reference/operator/aggregation/set.md#mongodb-pipeline-pipe.-set); [`$project`](https://www.mongodb.com/docs/manual/reference/operator/aggregation/project.md#mongodb-pipeline-pipe.-project) and its alias [`$unset`](https://www.mongodb.com/docs/manual/reference/operator/aggregation/unset.md#mongodb-pipeline-pipe.-unset); [`$replaceRoot`](https://www.mongodb.com/docs/manual/reference/operator/aggregation/replaceroot.md#mongodb-pipeline-pipe.-replaceRoot) and its alias [`$replaceWith`](https://www.mongodb.com/docs/manual/reference/operator/aggregation/replacewith.md#mongodb-pipeline-pipe.-replaceWith)The pipeline cannot modify the [on](https://www.mongodb.com/docs/manual/reference/operator/aggregation/merge.md#std-label-merge-on) field's value. For example, if you are matching on the field `month`, the pipeline cannot modify the `month` field.The whenMatched `pipeline` can directly access the fields of the existing documents in the **output** collection using `$<field>`.To access the fields from the aggregation results documents, use either:The built-in `$$new` variable to access the field. Specifically, `$$new.<field>`. The `$$new` variable is only available if the [let](https://www.mongodb.com/docs/manual/reference/operator/aggregation/merge.md#std-label-merge-let) specification is omitted.; The user-defined variables in the [let](https://www.mongodb.com/docs/manual/reference/operator/aggregation/merge.md#std-label-merge-let) field.Specify the double dollar sign ($$) prefix together with the variable name in the form `$$<variable_name>`. For example, `$$year`. If the variable is set to a document, you can also include a document field in the form `$$<variable_name>.<field>`. For example, `$$year.month`.For more examples, see [Use Variables to Customize the Merge.](https://www.mongodb.com/docs/manual/reference/operator/aggregation/merge.md#std-label-merge-variables-example) |
| [let](https://www.mongodb.com/docs/manual/reference/operator/aggregation/merge.md#std-label-merge-let) | Optional. Specifies variables for use in the [whenMatched pipeline.](https://www.mongodb.com/docs/manual/reference/operator/aggregation/merge.md#std-label-merge-whenMatched-pipeline) Specify a document with the variable names and value expressions: `{ <variable_name_1>: <expression_1>,
  ...,
  <variable_name_n>: <expression_n> }` If unspecified, defaults to `{ new: "$$ROOT" }` (see [`ROOT`](https://www.mongodb.com/docs/manual/reference/aggregation-variables.md#mongodb-variable-variable.ROOT)). The [whenMatched pipeline](https://www.mongodb.com/docs/manual/reference/operator/aggregation/merge.md#std-label-merge-whenMatched-pipeline) can access the `$$new` variable. To access the variables in the [whenMatched pipeline:](https://www.mongodb.com/docs/manual/reference/operator/aggregation/merge.md#std-label-merge-whenMatched-pipeline) Specify the double dollar sign ($$) prefix together with the variable name in the form `$$<variable_name>`. For example, `$$year`. If the variable is set to a document, you can also include a document field in the form `$$<variable_name>.<field>`. For example, `$$year.month`. For examples, see [Use Variables to Customize the Merge.](https://www.mongodb.com/docs/manual/reference/operator/aggregation/merge.md#std-label-merge-variables-example) |
| [whenNotMatched](https://www.mongodb.com/docs/manual/reference/operator/aggregation/merge.md#std-label-merge-whenNotMatched) | Optional. The behavior of `$merge` if a result document does not match an existing document in the out collection. You can specify one of the pre-defined action strings: ["insert"](https://www.mongodb.com/docs/manual/reference/operator/aggregation/merge.md#std-label-merge-whenNotMatched-insert) (Default):Insert the document into the output collection.; ["discard":](https://www.mongodb.com/docs/manual/reference/operator/aggregation/merge.md#std-label-merge-whenNotMatched-discard)Discard the document. Specifically, `$merge` does not insert the document into the output collection.; ["fail":](https://www.mongodb.com/docs/manual/reference/operator/aggregation/merge.md#std-label-merge-whenNotMatched-fail)Stop and fail the aggregation operation. Any changes already written to the output collection are not reverted. |

## Considerations

### `_id` Field Generation

If the `_id` field is not present in a document from the aggregation pipeline results, the `$merge` stage generates it automatically.

For example, in the following aggregation pipeline, [`$project`](https://www.mongodb.com/docs/manual/reference/operator/aggregation/project.md#mongodb-pipeline-pipe.-project) excludes the `_id` field from the documents passed into `$merge`. When `$merge` writes these documents to the `"newCollection"`, `$merge` generates a new `_id` field and value.

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

### Create a New Collection if Output Collection is Non-Existent

The `$merge` operation creates a new collection if the specified output collection does not exist.

- The output collection is created when `$merge` writes the first document into the collection and is immediately visible.

- If the aggregation fails, any writes completed by the `$merge` before the error will not be rolled back.

**Note:**

For a [replica set](https://www.mongodb.com/docs/manual/replication.md#std-label-replica-set) or a standalone, if the output database does not exist, `$merge` also creates the database.

For a [sharded cluster](https://www.mongodb.com/docs/manual/sharding.md#std-label-sharded-cluster), the specified output database must already exist.

If the output collection does not exist, `$merge` requires the [on](https://www.mongodb.com/docs/manual/reference/operator/aggregation/merge.md#std-label-merge-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](https://www.mongodb.com/docs/manual/reference/operator/aggregation/merge.md#std-label-merge-on) identifier:

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

### Output to a Sharded Collection

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](https://www.mongodb.com/docs/manual/core/sharding-shard-key.md#std-label-sharding-shard-key-creation) fields as the default [on](https://www.mongodb.com/docs/manual/reference/operator/aggregation/merge.md#std-label-merge-on) identifier. If you override the default, the [on](https://www.mongodb.com/docs/manual/reference/operator/aggregation/merge.md#std-label-merge-on) identifier must include all the [shard key](https://www.mongodb.com/docs/manual/core/sharding-shard-key.md#std-label-sharding-shard-key-creation) fields:

```javascript
{ $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
} }
```

For example, use the [`sh.shardCollection()`](https://www.mongodb.com/docs/manual/reference/method/sh.shardcollection.md#mongodb-method-sh.shardCollection) method to create a new sharded collection `moviesByYearAndRating` with the `rated` field as the shard key.

```javascript
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](https://www.mongodb.com/docs/manual/reference/operator/aggregation/merge.md#std-label-merge-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](https://www.mongodb.com/docs/manual/reference/operator/aggregation/merge.md#std-label-merge-on) identifier fields, create the unique index (the ordering of the fields do not matter):&#x20;

```javascript
db.moviesByYearAndRating.createIndex(
   { rated: 1, year: 1 }, { unique: true } )
```

With the sharded collection `moviesByYearAndRating` and the unique index created, you can use `$merge` to output the aggregation results to this collection, matching on `[ "year", "rated" ]` as in this example:

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

The [`sh.shardCollection()`](https://www.mongodb.com/docs/manual/reference/method/sh.shardcollection.md#mongodb-method-sh.shardCollection) method can also create a unique index on the shard key when passed the `{ unique: true
    }` option if: the shard key is [range-based](https://www.mongodb.com/docs/manual/core/ranged-sharding.md), the collection is empty, and a unique index on the shard key doesn't already exist.

In the previous example, because the `on` identifier is the shard key and another field, a separate operation to create the corresponding index is required.

### Replace Documents (`$merge`) vs Replace Collection (`$out`)

`$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](https://www.mongodb.com/docs/manual/reference/operator/aggregation/merge.md#std-label-merge-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"](https://www.mongodb.com/docs/manual/reference/operator/aggregation/merge.md#std-label-merge-whenMatched-replace) for [whenMatched.](https://www.mongodb.com/docs/manual/reference/operator/aggregation/merge.md#std-label-merge-whenMatched)

However, **to replace an existing collection** regardless of the aggregation results, use [`$out`](https://www.mongodb.com/docs/manual/reference/operator/aggregation/out.md#mongodb-pipeline-pipe.-out) instead.

### Existing Documents and `_id` and Shard Key Values

The `$merge` errors if the `$merge` results in a change to an existing document's `_id` value.

**Tip:**

To avoid this error, if the [on](https://www.mongodb.com/docs/manual/reference/operator/aggregation/merge.md#std-label-merge-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`](https://www.mongodb.com/docs/manual/reference/operator/aggregation/unset.md#mongodb-pipeline-pipe.-unset) stage, and so on.

Additionally, for a sharded collection, `$merge` also generates an error if it results in a change to the shard key value of an existing document.

Any writes completed by the `$merge` before the error will not be rolled back.

### Unique Index Constraints

If the unique index used by `$merge` for [on](https://www.mongodb.com/docs/manual/reference/operator/aggregation/merge.md#std-label-merge-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.

If the `$merge` attempts to write a document that violates any unique index on the output collection, the operation generates an error. For example:

- [Insert a non-matching document](https://www.mongodb.com/docs/manual/reference/operator/aggregation/merge.md#std-label-merge-whenNotMatched-insert) that violates a unique index other than the index on the [on](https://www.mongodb.com/docs/manual/reference/operator/aggregation/merge.md#std-label-merge-on) field(s).

- [Fail](https://www.mongodb.com/docs/manual/reference/operator/aggregation/merge.md#std-label-merge-whenMatched-fail) if there is a matching document in the collection. Specifically, the operation attempts to insert the matching document which violates the unique index on the [on](https://www.mongodb.com/docs/manual/reference/operator/aggregation/merge.md#std-label-merge-on) field(s).

- [Replace an existing document](https://www.mongodb.com/docs/manual/reference/operator/aggregation/merge.md#std-label-merge-whenMatched-replace) with a new document that violates a unique index other than the index on the [on](https://www.mongodb.com/docs/manual/reference/operator/aggregation/merge.md#std-label-merge-on) field(s).

- [Merge the matching documents](https://www.mongodb.com/docs/manual/reference/operator/aggregation/merge.md#std-label-merge-whenMatched-merge) that results in a document that violates a unique index other than the index on the [on](https://www.mongodb.com/docs/manual/reference/operator/aggregation/merge.md#std-label-merge-on) field(s).

### Schema Validation

If your collection uses [schema validation](https://www.mongodb.com/docs/manual/core/schema-validation.md#std-label-schema-validation-overview) and has `validationAction` set to `error`, inserting an invalid document or updating a document with invalid values with `$merge` throws a `MongoServerError` and the document is not written to the target collection. If there are multiple invalid documents, only the first invalid document encountered throws an error. All valid documents are written to the target collection, and all invalid documents fail to write.

### `whenMatched` Pipeline Behavior

`$merge` inserts the document directly into the output collection when all of the following are true:

- The value of [whenMatched](https://www.mongodb.com/docs/manual/reference/operator/aggregation/merge.md#std-label-merge-whenMatched) is an aggregation pipeline.

- The value of [whenNotMatched](https://www.mongodb.com/docs/manual/reference/operator/aggregation/merge.md#std-label-merge-whenNotMatched) is `insert`.

- There is no match for a document in the output collection.

### `$merge` and `$out` Comparison

With the introduction of `$merge`, MongoDB provides two stages, `$merge` and [`$out`](https://www.mongodb.com/docs/manual/reference/operator/aggregation/out.md#mongodb-pipeline-pipe.-out), for writing the results of the aggregation pipeline to a collection:

| `$merge` | [`$out`](https://www.mongodb.com/docs/manual/reference/operator/aggregation/out.md#mongodb-pipeline-pipe.-out) |
| --- | --- |
| Can output to a collection in the same or different database. | Can output to a collection in the same or different database. |
| Creates a new collection if the output collection does not already exist. | Creates a new collection if the output collection does not already exist. |
| Can incorporate results (insert new documents, merge documents, replace documents, keep existing documents, fail the operation, process documents with a custom update pipeline) into an existing collection.See also [Replace Documents (`$merge`) vs Replace Collection (`$out`)](https://www.mongodb.com/docs/manual/reference/operator/aggregation/merge.md#std-label-merge-behavior-replaceCollection). | Replaces the output collection completely if it already exists. |
| Can output to a sharded collection. Input collection can also be sharded. | Cannot output to a sharded collection. Input collection, however, can be sharded. |
| Corresponds to SQL statements:`MERGE`.; `INSERT INTO T2 SELECT FROM T1`.; `SELECT INTO T2 FROM T1`.; Create/Refresh Materialized Views. | Corresponds to SQL statement:`INSERT INTO T2 SELECT FROM T1`.; `SELECT INTO T2 FROM T1`. |

### Output to the Same Collection that is Being Aggregated

**Warning:**

When [`$merge`](https://www.mongodb.com/docs/manual/reference/operator/aggregation/merge.md#mongodb-pipeline-pipe.-merge) outputs to the same collection that is being aggregated, documents may get updated multiple times or the operation may result in an infinite loop. This behavior occurs when the update performed by [`$merge`](https://www.mongodb.com/docs/manual/reference/operator/aggregation/merge.md#mongodb-pipeline-pipe.-merge) changes the physical location of documents stored on disk. When the physical location of a document changes, [`$merge`](https://www.mongodb.com/docs/manual/reference/operator/aggregation/merge.md#mongodb-pipeline-pipe.-merge) may view it as an entirely new document, resulting in additional updates. For more information on this behavior, see [Halloween Problem.](https://en.wikipedia.org/wiki/Halloween_Problem)

[`$merge`](https://www.mongodb.com/docs/manual/reference/operator/aggregation/merge.md#mongodb-pipeline-pipe.-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`.](https://www.mongodb.com/docs/manual/reference/operator/aggregation/lookup.md#mongodb-pipeline-pipe.-lookup)

## Restrictions

| Restrictions | Description |
| --- | --- |
| [transactions](https://www.mongodb.com/docs/manual/core/transactions.md#std-label-transactions) | An aggregation pipeline cannot use `$merge` inside a [transaction.](https://www.mongodb.com/docs/manual/core/transactions-operations.md#std-label-transactions-operations-crud) |
| [Time Series Collections](https://www.mongodb.com/docs/manual/core/timeseries-collections.md#std-label-manual-timeseries-landing) | An aggregation pipeline cannot use `$merge` to output to a time series collection. |
| [view definition](https://www.mongodb.com/docs/manual/core/views.md#std-label-views-landing-page)*Separate from materialized view* | A view definition cannot include the `$merge` stage. If the view definition includes nested pipeline (for example, the view definition includes [`$facet`](https://www.mongodb.com/docs/manual/reference/operator/aggregation/facet.md#mongodb-pipeline-pipe.-facet) stage), this `$merge` stage restriction applies to the nested pipelines as well. |
| [`$lookup`](https://www.mongodb.com/docs/manual/reference/operator/aggregation/lookup.md#mongodb-pipeline-pipe.-lookup) stage | [`$lookup`](https://www.mongodb.com/docs/manual/reference/operator/aggregation/lookup.md#mongodb-pipeline-pipe.-lookup) stage's [nested pipeline](https://www.mongodb.com/docs/manual/reference/operator/aggregation/lookup.md#std-label-lookup-syntax-let-pipeline) cannot include the `$merge` stage. |
| [`$facet`](https://www.mongodb.com/docs/manual/reference/operator/aggregation/facet.md#mongodb-pipeline-pipe.-facet) stage | [`$facet`](https://www.mongodb.com/docs/manual/reference/operator/aggregation/facet.md#mongodb-pipeline-pipe.-facet) stage's [nested pipeline](https://www.mongodb.com/docs/manual/reference/operator/aggregation/lookup.md#std-label-lookup-syntax-let-pipeline) cannot include the `$merge` stage. |
| [`$unionWith`](https://www.mongodb.com/docs/manual/reference/operator/aggregation/unionwith.md#mongodb-pipeline-pipe.-unionWith) stage | [`$unionWith`](https://www.mongodb.com/docs/manual/reference/operator/aggregation/unionwith.md#mongodb-pipeline-pipe.-unionWith) stage's [nested pipeline](https://www.mongodb.com/docs/manual/reference/operator/aggregation/unionwith.md#std-label-unionWith-pipeline) cannot include the `$merge` stage. |
| [`"linearizable"`](https://www.mongodb.com/docs/manual/reference/read-concern-linearizable.md#mongodb-readconcern-readconcern.-linearizable-) read concern | The [`$merge`](https://www.mongodb.com/docs/manual/reference/operator/aggregation/merge.md#mongodb-pipeline-pipe.-merge) stage cannot be used in conjunction with read concern [`"linearizable"`](https://www.mongodb.com/docs/manual/reference/read-concern-linearizable.md#mongodb-readconcern-readconcern.-linearizable-). That is, if you specify [`"linearizable"`](https://www.mongodb.com/docs/manual/reference/read-concern-linearizable.md#mongodb-readconcern-readconcern.-linearizable-) read concern for [`db.collection.aggregate()`](https://www.mongodb.com/docs/manual/reference/method/db.collection.aggregate.md#mongodb-method-db.collection.aggregate), you cannot include the [`$merge`](https://www.mongodb.com/docs/manual/reference/operator/aggregation/merge.md#mongodb-pipeline-pipe.-merge) stage in the pipeline. |

## Examples

The examples on this page use data from the [sample\_mflix dataset](https://www.mongodb.com/docs/manual/sample-data/sample-mflix.md#std-label-sample-mflix). For details on how to load this dataset into your self-managed MongoDB deployment, see [Load the Sample Dataset](https://www.mongodb.com/docs/manual/sample-data/load-sample-data-local.md#std-label-sample-dataset-local). If you made any modifications to the sample databases, you may need to drop and recreate the databases to run the examples on this page.

### On-Demand Materialized View: Initial Creation

If the output collection does not exist, the `$merge` creates the collection.

**Note:**

For a replica set or a standalone deployment, if the output database does not exist, `$merge` also creates the database.

For a sharded cluster deployment, the specified output database must already exist.

You can use the [`$group`](https://www.mongodb.com/docs/manual/reference/operator/aggregation/group.md#mongodb-pipeline-pipe.-group) and `$merge` stages to create a `movieRatingSummary` collection that summarizes critically acclaimed films by release year and content rating:

```javascript
db.movies.aggregate( [
   { $match: { metacritic: 100, rated: { $ne: null },
     year: { $lte: 1972 } } },
   { $group: { _id: { year: "$year", rated: "$rated" },
     count: { $sum: 1 } } },
   { $merge : { into: "movieRatingSummary", on: "_id",
     whenMatched: "replace", whenNotMatched: "insert" } }
] )

```

The pipeline uses the following stages:

- [`$match`](https://www.mongodb.com/docs/manual/reference/operator/aggregation/match.md#mongodb-pipeline-pipe.-match) stage to filter for critically acclaimed films released through 1972 with a content rating

- [`$group`](https://www.mongodb.com/docs/manual/reference/operator/aggregation/group.md#mongodb-pipeline-pipe.-group) stage to group the films by `year` and `rated`

- `$merge` stage to write the output of the preceding [`$group`](https://www.mongodb.com/docs/manual/reference/operator/aggregation/group.md#mongodb-pipeline-pipe.-group) stage to the `movieRatingSummary` collection in the `sample_mflix` database

To view the documents in the new `movieRatingSummary` collection:

```javascript
db.movieRatingSummary.find().sort(
   { _id: 1 } )

```

**Output:**

```javascript
[
  { _id: { year: 1939, rated: 'PASSED' }, count: 1 },
  { _id: { year: 1962, rated: 'PG' }, count: 1 },
  { _id: { year: 1963, rated: 'PG' }, count: 1 },
  { _id: { year: 1970, rated: 'R' }, count: 1 },
  { _id: { year: 1972, rated: 'R' }, count: 1 }
]

```

**See also:**

[On-Demand Materialized Views](https://www.mongodb.com/docs/manual/core/materialized-views.md)

### On-Demand Materialized View: Update/Replace Data

To update the `movieRatingSummary` collection from the previous example to include critically acclaimed films from 1963 onward, this aggregation pipeline uses the following stages:

- [`$match`](https://www.mongodb.com/docs/manual/reference/operator/aggregation/match.md#mongodb-pipeline-pipe.-match) stage to find all films with `metacritic: 100`, a content rating, and a release year greater than or equal to `1963`.

- [`$group`](https://www.mongodb.com/docs/manual/reference/operator/aggregation/group.md#mongodb-pipeline-pipe.-group) stage to group the films by `year` and `rated`.

- `$merge` to write the result set to the `movieRatingSummary` collection, [replacing documents](https://www.mongodb.com/docs/manual/reference/operator/aggregation/merge.md#std-label-merge-whenMatched-replace) with the same `_id` value. For documents that do not have matches in the collection, `$merge` inserts the new documents.

```javascript
db.movies.aggregate( [
   { $match: { metacritic: 100, rated: { $ne: null },
     year: { $gte: 1963 } } },
   { $group: { _id: { year: "$year", rated: "$rated" },
     count: { $sum: 1 } } },
   { $merge : { into: "movieRatingSummary", on: "_id",
     whenMatched: "replace", whenNotMatched: "insert" } }
] )

```

After the aggregation runs, view the documents in the `movieRatingSummary` collection:

```javascript
db.movieRatingSummary.find().sort(
   { _id: 1 } )

```

**Output:**

```javascript
[
  { _id: { year: 1939, rated: 'PASSED' }, count: 1 },
  { _id: { year: 1962, rated: 'PG' }, count: 1 },
  { _id: { year: 1963, rated: 'PG' }, count: 1 },
  { _id: { year: 1970, rated: 'R' }, count: 1 },
  { _id: { year: 1972, rated: 'R' }, count: 1 },
  { _id: { year: 1982, rated: 'R' }, count: 1 },
  { _id: { year: 2014, rated: 'R' }, count: 1 }
]

```

**See also:**

[On-Demand Materialized Views](https://www.mongodb.com/docs/manual/core/materialized-views.md)

### Only Insert New Data

To ensure that the `$merge` does not overwrite existing data in the collection, set [whenMatched](https://www.mongodb.com/docs/manual/reference/operator/aggregation/merge.md#std-label-merge-whenMatched) to [keepExisting](https://www.mongodb.com/docs/manual/reference/operator/aggregation/merge.md#std-label-merge-whenMatched-keepExisting) or [fail.](https://www.mongodb.com/docs/manual/reference/operator/aggregation/merge.md#std-label-merge-whenMatched-fail)

A collection `movieArchive` in the `sample_mflix` database contains historical records of critically acclaimed films per release year.

The `movieArchive` collection has a unique index on the `year` field. At most one record should exist per release year:

```javascript
db.movieArchive.createIndex(
   { year: 1 }, { unique: true } )

```

This aggregation pipeline updates the `movieArchive` collection with data from the `movies` collection to include critically acclaimed films from 1963 onward. The pipeline uses the following stages:

- [`$match`](https://www.mongodb.com/docs/manual/reference/operator/aggregation/match.md#mongodb-pipeline-pipe.-match) stage to find all films with `metacritic: 100`, a content rating, and `year >= 1963`.

- [`$group`](https://www.mongodb.com/docs/manual/reference/operator/aggregation/group.md#mongodb-pipeline-pipe.-group) stage to group the film titles by `year`.

- [`$project`](https://www.mongodb.com/docs/manual/reference/operator/aggregation/project.md#mongodb-pipeline-pipe.-project) stage to suppress the `_id` field and promote `year` to a top-level field. When the documents are passed to `$merge`, `$merge` automatically generates a new `_id` field for the documents.

- `$merge` to write the result set to `movieArchive`.

  The `$merge` stage matches documents [on](https://www.mongodb.com/docs/manual/reference/operator/aggregation/merge.md#std-label-merge-on) the `year` field and fails when matched. That is, if a document already exists for that release year, the `$merge` errors.

```javascript
db.movies.aggregate( [
   { $match: { metacritic: 100, rated: { $ne: null },
     year: { $gte: 1963 } } },
   { $group: { _id: "$year",
     titles: { $push: "$title" } } },
   { $project: { _id: 0, year: "$_id", titles: 1 } },
   { $merge : { into: "movieArchive", on: "year",
     whenMatched: "fail" } }
] )

```

If the `movieArchive` collection already contains a document for any year in the range 1963–2014, the aggregation [fails because of the duplicate key error](https://www.mongodb.com/docs/manual/reference/operator/aggregation/merge.md#std-label-merge-unique-index-constraints). However, the pipeline does not roll back any documents that it inserted before the error.

If you specify [keepExisting](https://www.mongodb.com/docs/manual/reference/operator/aggregation/merge.md#std-label-merge-whenMatched-keepExisting) for the matching document, the aggregation does not affect the matching document and does not error with a duplicate key error. Similarly, if you specify [replace](https://www.mongodb.com/docs/manual/reference/operator/aggregation/merge.md#std-label-merge-whenMatched-replace), the operation does not fail; however, the operation replaces the existing document.

### Merge Results from Multiple Collections

By default, if a document in the aggregation results matches a document in the collection, the `$merge` stage [merges](https://www.mongodb.com/docs/manual/reference/operator/aggregation/merge.md#std-label-merge-whenMatched-merge) the documents.

You can use `$merge` to merge results from the `movies` collection and the `comments` collection to create a new collection `yearlyStats`.

To create the `yearlyStats` collection, run the following pipeline:

```javascript
db.movies.aggregate( [
   { $match: { metacritic: 100, rated: { $ne: null },
     year: { $gte: 1970, $lte: 1972 } } },
   { $group: { _id: "$year", movieCount: { $sum: 1 } } },
   { $merge : { into: "yearlyStats", on: "_id",
     whenMatched: "merge", whenNotMatched: "insert" } }
])

```

First stage:

The [`$match`](https://www.mongodb.com/docs/manual/reference/operator/aggregation/match.md#mongodb-pipeline-pipe.-match) stage filters for critically acclaimed films (`metacritic: 100`) with a content rating, released between 1970 and 1972.

Second stage:

The [`$group`](https://www.mongodb.com/docs/manual/reference/operator/aggregation/group.md#mongodb-pipeline-pipe.-group) stage groups by `year` and counts films into a new `movieCount` field.

Third stage:

The `$merge` stage writes the documents to the `yearlyStats` collection in the same database. If the stage finds an existing document in the collection that [matches on](https://www.mongodb.com/docs/manual/reference/operator/aggregation/merge.md#std-label-merge-on) the `_id` field, the stage merges the matching documents. Otherwise, the stage inserts the document. For the initial creation, no documents match.

To view the documents in the collection, run the following operation:

```javascript
db.yearlyStats.find().sort( { _id: 1 } )

```

**Output:**

```javascript
[
  { _id: 1970, movieCount: 1 },
  { _id: 1972, movieCount: 1 }
]

```

Similarly, run the following aggregation pipeline against the `comments` collection to merge the comment counts into the `yearlyStats` collection.

```javascript
db.comments.aggregate( [
   { $match: { date: { $gte: new Date("1970-01-01"),
     $lt: new Date("1973-01-01") } } },
   { $group: { _id: { $year: "$date" },
     commentCount: { $sum: 1 } } },
   { $merge : { into: "yearlyStats", on: "_id",
     whenMatched: "merge", whenNotMatched: "insert" } }
])

```

First stage:

The [`$match`](https://www.mongodb.com/docs/manual/reference/operator/aggregation/match.md#mongodb-pipeline-pipe.-match) stage filters for comments posted between 1970 and 1972.

Second stage:

The [`$group`](https://www.mongodb.com/docs/manual/reference/operator/aggregation/group.md#mongodb-pipeline-pipe.-group) stage groups by the year extracted from the comment `date` and counts comments into a new `commentCount` field.

Third stage:

The `$merge` stage writes the documents to the `yearlyStats` collection in the same database. If the stage finds an existing document in the collection that [matches on](https://www.mongodb.com/docs/manual/reference/operator/aggregation/merge.md#std-label-merge-on) the `_id` field (the year), the stage merges the matching documents. Otherwise, the stage inserts the document.

To view the documents in the `yearlyStats` collection after the data has been merged, run the following operation:

```javascript
db.yearlyStats.find().sort( { _id: 1 } )

```

**Output:**

```javascript
[
  { _id: 1970, movieCount: 1, commentCount: 889 },
  { _id: 1971, commentCount: 825 },
  { _id: 1972, movieCount: 1, commentCount: 863 }
]

```

### Use the Pipeline to Customize the Merge

The `$merge` can use a [custom update pipeline](https://www.mongodb.com/docs/manual/reference/operator/aggregation/merge.md#std-label-merge-whenMatched-pipeline) when documents match. The [whenMatched pipeline](https://www.mongodb.com/docs/manual/reference/operator/aggregation/merge.md#std-label-merge-whenMatched-pipeline) can have the following stages:

- [`$addFields`](https://www.mongodb.com/docs/manual/reference/operator/aggregation/addfields.md#mongodb-pipeline-pipe.-addFields) and its alias [`$set`](https://www.mongodb.com/docs/manual/reference/operator/aggregation/set.md#mongodb-pipeline-pipe.-set)

- [`$project`](https://www.mongodb.com/docs/manual/reference/operator/aggregation/project.md#mongodb-pipeline-pipe.-project) and its alias [`$unset`](https://www.mongodb.com/docs/manual/reference/operator/aggregation/unset.md#mongodb-pipeline-pipe.-unset)

- [`$replaceRoot`](https://www.mongodb.com/docs/manual/reference/operator/aggregation/replaceroot.md#mongodb-pipeline-pipe.-replaceRoot) and its alias [`$replaceWith`](https://www.mongodb.com/docs/manual/reference/operator/aggregation/replacewith.md#mongodb-pipeline-pipe.-replaceWith)

A collection `monthlyCommentTotals` tracks the running count of comments for each month.

Each day, new comments arrive in the `sample_mflix.comments` collection. The following aggregation pipeline updates the monthly total with that day's comment count:

```javascript
db.comments.aggregate([
   { $match: { date: { $gte: new Date("1970-01-15"),
     $lt: new Date("1970-01-16") } } },
   { $group: { _id: { $dateToString: { format: "%Y-%m",
     date: "$date" } }, count: { $sum: 1 } } },
   { $merge: {
         into: "monthlyCommentTotals",
         on: "_id",
         whenMatched: [
            { $addFields: {
               count: { $add: [ "$count", "$$new.count" ] }
            } }
         ],
         whenNotMatched: "insert"
   } }
])

```

First stage:

The [`$match`](https://www.mongodb.com/docs/manual/reference/operator/aggregation/match.md#mongodb-pipeline-pipe.-match) stage finds all comments posted on January 15, 1970.

Second stage:

The [`$group`](https://www.mongodb.com/docs/manual/reference/operator/aggregation/group.md#mongodb-pipeline-pipe.-group) stage groups the matching comments by year-month and counts them.

Third stage:

The `$merge` stage writes the documents to the `monthlyCommentTotals` collection. If the stage finds an existing document in the collection that [matches on](https://www.mongodb.com/docs/manual/reference/operator/aggregation/merge.md#std-label-merge-on) the `_id` field, the stage uses a pipeline to add the day's `count` to the existing monthly total.

- This pipeline cannot directly access the fields from the results document. To access the `count` field in the results document, the pipeline uses the `$$new` variable; i.e. `$$new.count`.

- This pipeline can directly access the `count` field in the existing document in the collection; i.e. `$count`.

The resulting document replaces the existing document.

To view documents in the `monthlyCommentTotals` collection after the merge operation, run the following operation:

```javascript
db.monthlyCommentTotals.find()

```

**Output:**

```javascript
[ { _id: '1970-01', count: 71 } ]

```

### Use Variables to Customize the Merge

You can use variables in the `$merge` stage [whenMatched](https://www.mongodb.com/docs/manual/reference/operator/aggregation/merge.md#std-label-merge-whenMatched-pipeline) field. Variables must be defined before they can be used.

Define variables in one or both of the following:

- `$merge` stage [let](https://www.mongodb.com/docs/manual/reference/operator/aggregation/merge.md#std-label-merge-let)

- [`aggregate`](https://www.mongodb.com/docs/manual/reference/command/aggregate.md#mongodb-dbcommand-dbcmd.aggregate) command [let](https://www.mongodb.com/docs/manual/reference/command/aggregate.md#std-label-aggregate-let-option) (starting in MongoDB 5.0)

To use variables in [whenMatched:](https://www.mongodb.com/docs/manual/reference/operator/aggregation/merge.md#std-label-merge-whenMatched-pipeline)

Specify the double dollar sign ($$) prefix together with the variable name in the form `$$<variable_name>`. For example, `$$year`. If the variable is set to a document, you can also include a document field in the form `$$<variable_name>.<field>`. For example, `$$year.month`.

The tabs below demonstrate behavior when variables are defined in the merge stage, the aggregate command, or both.

#### Use Variables Defined in the Merge Stage

You can define variables in the `$merge` stage [let](https://www.mongodb.com/docs/manual/reference/operator/aggregation/merge.md#std-label-merge-let) and use the variables in the [whenMatched](https://www.mongodb.com/docs/manual/reference/operator/aggregation/merge.md#std-label-merge-whenMatched-pipeline) field.

The following example:

- seeds a `movieDetails` collection with a film from the `movies` collection

- runs an [`aggregate`](https://www.mongodb.com/docs/manual/reference/command/aggregate.md#mongodb-dbcommand-dbcmd.aggregate) command that defines a `year` variable in the `$merge` [let](https://www.mongodb.com/docs/manual/reference/operator/aggregation/merge.md#std-label-merge-let) and adds the year to `movieDetails` using [whenMatched](https://www.mongodb.com/docs/manual/reference/operator/aggregation/merge.md#std-label-merge-whenMatched-pipeline)

- retrieves the `movieDetails` document

```javascript
db.movies.aggregate( [
   { $match: { title: "The Godfather" } },
   { $limit: 1 },
   { $project: { title: 1 } },
   { $merge: { into: "movieDetails", whenNotMatched: "insert" } }
] )

db.runCommand( {
   aggregate: db.movieDetails.getName(),
   pipeline: [ {
      $merge: {
         into: db.movieDetails.getName(),
         let : { year: "2023" },
         whenMatched: [ {
            $addFields: { "addedYear": "$$year" }
         } ]
      }
   } ],
   cursor: {}
} )

db.movieDetails.find()

```

**Output:**

```javascript
[ { _id: ..., title: 'The Godfather', addedYear: '2023' } ]

```

#### Use Variables Defined in the Aggregate Command

**New in version 5.0**

You can define variables in the [`aggregate`](https://www.mongodb.com/docs/manual/reference/command/aggregate.md#mongodb-dbcommand-dbcmd.aggregate) command [let](https://www.mongodb.com/docs/manual/reference/command/aggregate.md#std-label-aggregate-let-option) and use the variables in the `$merge` stage [whenMatched](https://www.mongodb.com/docs/manual/reference/operator/aggregation/merge.md#std-label-merge-whenMatched-pipeline) field.

The following example:

- seeds a `movieDetails` collection with a film from the `movies` collection

- runs an [`aggregate`](https://www.mongodb.com/docs/manual/reference/command/aggregate.md#mongodb-dbcommand-dbcmd.aggregate) command that defines a `year` variable in the [`aggregate`](https://www.mongodb.com/docs/manual/reference/command/aggregate.md#mongodb-dbcommand-dbcmd.aggregate) command [let](https://www.mongodb.com/docs/manual/reference/command/aggregate.md#std-label-aggregate-let-option) and adds the year to `movieDetails` using [whenMatched](https://www.mongodb.com/docs/manual/reference/operator/aggregation/merge.md#std-label-merge-whenMatched-pipeline)

- retrieves the `movieDetails` document

```javascript
db.movies.aggregate( [
   { $match: { title: "The Godfather" } },
   { $limit: 1 },
   { $project: { title: 1 } },
   { $merge: { into: "movieDetails", whenNotMatched: "insert" } }
] )

db.runCommand( {
   aggregate: db.movieDetails.getName(),
   pipeline: [ {
      $merge: {
         into: db.movieDetails.getName(),
         whenMatched: [ {
            $addFields: { "addedYear": "$$year" }
         } ]
      }
   } ],
   cursor: {},
   let : { year: "2023" }
} )

db.movieDetails.find()

```

**Output:**

```javascript
[ { _id: ..., title: 'The Godfather', addedYear: '2023' } ]

```

#### Use Variables Defined in the Merge Stage and Aggregate Command

You can define variables in the `$merge` stage and, starting in MongoDB 5.0, the [`aggregate`](https://www.mongodb.com/docs/manual/reference/command/aggregate.md#mongodb-dbcommand-dbcmd.aggregate) command.

If two variables with the same name are defined in the `$merge` stage and the [`aggregate`](https://www.mongodb.com/docs/manual/reference/command/aggregate.md#mongodb-dbcommand-dbcmd.aggregate) command, the `$merge` stage variable is used.

In this example, the pipeline uses `year: "2023"` instead of the `year: "2019"` [`aggregate`](https://www.mongodb.com/docs/manual/reference/command/aggregate.md#mongodb-dbcommand-dbcmd.aggregate) command variable:

```javascript
db.movies.aggregate( [
   { $match: { title: "The Godfather" } },
   { $limit: 1 },
   { $project: { title: 1 } },
   { $merge: { into: "movieDetails", whenNotMatched: "insert" } }
] )

db.runCommand( {
   aggregate: db.movieDetails.getName(),
   pipeline: [ {
      $merge: {
         into: db.movieDetails.getName(),
         let : { year: "2023" },
         whenMatched: [ {
            $addFields: { "addedYear": "$$year" }
         } ]
      }
   } ],
   cursor: {},
   let : { year: "2019" }
} )

db.movieDetails.find()

```

**Output:**

```javascript
[ { _id: ..., title: 'The Godfather', addedYear: '2023' } ]

```

The following `Movie` class models the documents used in this example:

```csharp
[BsonIgnoreExtraElements]
public class Movie
{
    [BsonId]
    public ObjectId Id { get; set; }
    [BsonElement("title")]
    public string Title { get; set; } = null!;
    [BsonElement("year")]
    public int? Year { get; set; }
    [BsonElement("runtime")]
    public int? Runtime { get; set; }
    [BsonElement("rated")]
    public string? Rated { get; set; }
    [BsonElement("metacritic")]
    public int Metacritic { get; set; }
    [BsonElement("plot")]
    public string? Plot { get; set; }
    [BsonElement("type")]
    public string? Type { get; set; }
    [BsonElement("cast")]
    public string[]? Cast { get; set; }
    [BsonElement("directors")]
    public string[]? Directors { get; set; }
    [BsonElement("writers")]
    public string[]? Writers { get; set; }
    [BsonElement("imdb")]
    public ImdbData? Imdb { get; set; }
}

```

To use the MongoDB .NET/C# driver to add a `$merge` stage to an aggregation pipeline, call the [UnionWith()](https://mongodb.github.io/mongo-csharp-driver/3.11.0/api/MongoDB.Driver/MongoDB.Driver.PipelineStageDefinitionBuilder.UnionWith.html) method on a `PipelineDefinition` object.

When you call the `Merge()` method, you must pass an instance of the [MergeStageOptions](https://mongodb.github.io/mongo-csharp-driver/3.11.0/api/MongoDB.Driver/MongoDB.Driver.MergeStageOptions-1.html) class. This object lets you specify options for the `$merge` stage, such as how to handle matching documents.

The following example creates a pipeline stage that merges the documents in the pipeline into the `movies` collection. The `MergeStageOptions` object specifies the following options:

- The `OnFieldNames` option specifies that the operation should use the `"_id"` field to identify matching documents.

- The `WhenMatched` option specifies that if a document in the source collection matches a document in the target collection, the operation replaces the matched document.

- The `WhenNotMatched` option specifies that if a document in the source collection does not match a document in the target collection, the operation inserts the document into the target collection.

```csharp
var pipeline = new EmptyPipelineDefinition<Movie>()
    .Merge(_targetCollection,
        new MergeStageOptions<Movie>()
        {
            OnFieldNames = new List<string>() { "_id" },
            WhenMatched = MergeStageWhenMatched.Replace,
            WhenNotMatched = MergeStageWhenNotMatched.Insert,
        });

```

**Output:**

```json
{ "_id": "...", "title": "Back to the Future", "metacritic": 96 }
{ "_id": "...", "title": "Jurassic Park", "metacritic": 68 }
{ "_id": "...", "title": "The Shawshank Redemption", "metacritic": 80 }

```

The Node.js examples on this page use the `sample_mflix` database from the [Atlas sample datasets](https://www.mongodb.com/docs/atlas/sample-data/). To learn how to create a free MongoDB Atlas cluster and load the sample datasets, see [Get Started](https://www.mongodb.com/docs/drivers/node/current/get-started/) in the MongoDB Node.js driver documentation.

To use the MongoDB Node.js driver to add a `$merge` stage to an aggregation pipeline, use the `$merge` operator in a pipeline object.

The following example creates a pipeline stage that merges the documents in the pipeline into the `movies` collection. The example includes the following fields:

- The `on` option specifies that the operation should use the `"_id"` and `"title"` fields to find matching documents in the source collection and the `movies` collection.

- The `whenMatched` option specifies that if a document in the source collection matches a document in the `movies` collection, it replaces the document in the `movies` collection.

- The `whenNotMatched` option specifies that if a document in the source collection does not match a document in the `movies` collection, the operation inserts the document into the `movies` collection.

The example then runs the aggregation pipeline:

```javascript
const pipeline = [
  {
    $merge: {
      into: "movies",
      on: ["_id", "title"],
      whenMatched: "replace",
      whenNotMatched: "insert"
    }
  }
];

const cursor = collection.aggregate(pipeline);
return cursor;
```
