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

<!--
Tab options on this page. Append to the .md URL to filter:
  ?tabs=<id,...>   select specific tabs (e.g. ?tabs=nodejs,shell)
  ?allTabs=true    include every tab
  (no param)       default: one tab per tabset

Available tabs:
  drivers: shell, csharp, nodejs
-->

# $out (aggregation stage)

## Definition

Takes the documents returned by the aggregation pipeline and writes them to a specified collection. You can specify the output database.

The `$out` stage must be *the last stage* in the pipeline. The `$out` operator lets the aggregation framework return result sets of any size.

**Warning:**

If the collection specified by the `$out` operation already exists, then the `$out` stage atomically replaces the existing collection with the new results collection upon completion of the aggregation. See [Replace Existing Collection](https://www.mongodb.com/docs/manual/reference/operator/aggregation/out.md#std-label-replace-existing-collection) for details.

## Syntax

The `$out` stage has the following syntax:

- `$out` can take a string to specify only the output collection (i.e. output to a collection in the same database):

  ```javascript
  { $out: "<output-collection>" } // Output collection is in the same database
  ```

- `$out` can take a document to specify the output database as well as the output collection:

  ```javascript
  { $out: { db: "<output-db>", coll: "<output-collection>" } }
  ```

- Starting in MongoDB 7.0.3 and 7.1, `$out` can take a document to output to a [time series collection:](https://www.mongodb.com/docs/manual/core/timeseries-collections.md#std-label-manual-timeseries-landing)

  ```javascript
  { $out:
    { db: "<output-db>", coll: "<output-collection>",
      timeseries: {
        timeField: "<field-name>",
        metaField: "<field-name>",
        granularity:  "seconds" || "minutes" || "hours" ,
      }
    }
  }
  ```

  **Important: Changing Time Series Granularity**

  After creating a time series collection, you can modify its granularity using the [`collMod`](https://www.mongodb.com/docs/manual/reference/command/collmod.md#mongodb-dbcommand-dbcmd.collMod) method. However, you can only increase the timespan covered by each bucket. You cannot decrease it.

  | Field | Description |
  | --- | --- |
  | `db` | The output database name. 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, `$out` also creates the database. |
  | `coll` | The output collection name. |
  | `timeseries` | A document that specifies the configuration to use when writing to a time series collection. The `timeField` is required. All other fields are optional. |
  | `timeField` | Required when writing to a time series collection. The name of the field which contains the date in each time series document. Documents in a time series collection must have a valid BSON date as the value for the `timeField`. |
  | `metaField` | Optional. The name of the field which contains metadata in each time series document. The metadata in the specified field should be data that is used to label a unique series of documents. The metadata should rarely, if ever, change The name of the specified field may not be `_id` or the same as the `timeseries.timeField`. The field can be of any data type. Although the `metaField` field is optional, using metadata can improve query optimization. For example, MongoDB automatically [creates a compound index](https://www.mongodb.com/docs/manual/core/timeseries/timeseries-secondary-index.md#std-label-timeseries-add-secondary-index) on the `metaField` and `timeField` fields for new collections. If you do not provide a value for this field, the data is bucketed solely based on time. |
  | `granularity` | Optional. Do not use if setting `bucketRoundingSeconds` and `bucketMaxSpanSeconds`. Possible values are `seconds` (default), `minutes`, and `hours`. Set `granularity` to the value that most closely matches the time between consecutive incoming timestamps. This improves performance by optimizing how MongoDB stores data in the collection. For more information on granularity and bucket intervals, see [Set Granularity for Time Series Data.](https://www.mongodb.com/docs/manual/core/timeseries/timeseries-granularity.md#std-label-timeseries-granularity) |
  | `bucketMaxSpanSeconds` | Optional. Use with `bucketRoundingSeconds` as an alternative to `granularity`. Sets the maximum time between timestamps in the same bucket. Possible values are 1-31536000. **New in version 6.3** |
  | `bucketRoundingSeconds` | Optional. Use with `bucketMaxSpanSeconds` as an alternative to `granularity`. Must be equal to `bucketMaxSpanSeconds`. When a document requires a new bucket, MongoDB rounds down the document's timestamp value by this interval to set the minimum time for the bucket. **New in version 6.3** |

**Important:**

- You cannot specify a sharded collection as the output collection. The input collection for a pipeline can be sharded. To output to a sharded collection, see [`$merge`.](https://www.mongodb.com/docs/manual/reference/operator/aggregation/merge.md#mongodb-pipeline-pipe.-merge)

- The `$out` operator cannot write results to a [capped collection.](https://www.mongodb.com/docs/manual/core/capped-collections.md#std-label-manual-capped-collection)

- If you modify a collection with a [MongoDB Search](https://www.mongodb.com/docs/atlas/atlas-search/) index, you must first delete and then re-create the search index. Consider using [`$merge`](https://www.mongodb.com/docs/manual/reference/operator/aggregation/merge.md#mongodb-pipeline-pipe.-merge) instead.

### Comparison with `$merge`

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

| `$out` | [`$merge`](https://www.mongodb.com/docs/manual/reference/operator/aggregation/merge.md#mongodb-pipeline-pipe.-merge) |
| --- | --- |
| 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. |
| Replaces the output collection completely if it already exists. | 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 replace the content of the collection but only if the aggregation results contain a match for all existing documents in the collection. |
| Cannot output to a sharded collection. Input collection, however, can be sharded. | Can output to a sharded collection. Input collection can also be sharded. |
| Starting in MongoDB 7.0.3 and 7.1, can output to a time series collection. | Cannot output to a time series collection. |
| Corresponds to the SQL statements:`INSERT INTO T2 SELECT * FROM T1`; `SELECT * INTO T2 FROM T1` | Corresponds to the SQL statement:`MERGE T2 AS TARGET
USING (SELECT * FROM T1) AS SOURCE
ON MATCH (T2.ID = SOURCE.ID)
WHEN MATCHED THEN
  UPDATE SET TARGET.FIELDX = SOURCE.FIELDY
WHEN NOT MATCHED THEN
  INSERT (FIELDX)
  VALUES (SOURCE.FIELDY)`; Create/Refresh Materialized Views |

## Behaviors

### $out Read Operations Run on Secondary Replica Set Members

Starting in MongoDB 5.0, `$out` can run on replica set secondary nodes if all the nodes in cluster have [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) is set to secondary.

Read operations of the `$out` statement occur on the secondary nodes, while the write operations occur only on the primary nodes.

Not all driver versions support targeting of `$out` operations to replica set secondary nodes. Check your [driver](https://www.mongodb.com/docs/drivers/) documentation to see when your driver added support for `$out` running on a secondary.

### Create New Collection

The `$out` operation creates a new collection if one does not already exist.

The collection is not visible until the aggregation completes. If the aggregation fails, MongoDB does not create the collection.

### Replace Existing Collection

If the output collection already exists, the `$out` stage atomically replaces it upon completion of the aggregation. Specifically, the `$out` operation:

1. Creates a temp collection.

2. Copies the index definitions from the existing collection to the temp collection.

3. Inserts the documents into the temp collection.

4. Calls the [`renameCollection`](https://www.mongodb.com/docs/manual/reference/command/renamecollection.md#mongodb-dbcommand-dbcmd.renameCollection) command with `dropTarget: true` to rename the temp collection to the destination collection.

If specified collection exists and the `$out` operation specifies `timeseries` options, then the following restrictions apply:

1. The existing collection must be a time series collection.

2. The existing collection must not be a view.

3. The `timeseries` options included in the `$out` stage must exactly match those on the existing collection.

The `$out` operation copies the index definitions from the existing collection and recreates the indexes for the replacement collection. The resulting indexes match the index rules on the original collection and the data that the aggregation pipeline writes. If the aggregation fails, the `$out` operation makes no changes to the pre-existing collection.

#### Schema Validation Errors

If your `coll` 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 with `$out` throws an error. The `$out` operation makes no changes to the pre-existing collection and documents returned by the aggregation pipeline are not added to the `coll` collection.

### Index Constraints

The pipeline will fail to complete if the documents produced by the pipeline would violate any unique indexes, including the index on the `_id` field of the original output collection.

If the `$out` operation modifies a collection with a [MongoDB Search](https://www.mongodb.com/docs/atlas/atlas-search/) index, you must delete and re-create the search index. Consider using [`$merge`](https://www.mongodb.com/docs/manual/reference/operator/aggregation/merge.md#mongodb-pipeline-pipe.-merge) instead.

### `majority` Read Concern

You can specify [read concern](https://www.mongodb.com/docs/manual/reference/read-concern.md#std-label-read-concern) level [`"majority"`](https://www.mongodb.com/docs/manual/reference/read-concern-majority.md#mongodb-readconcern-readconcern.-majority-) for an aggregation that includes an [`$out`](https://www.mongodb.com/docs/manual/reference/operator/aggregation/out.md#mongodb-pipeline-pipe.-out) stage.

### Interaction with `mongodump`

A [`mongodump`](https://www.mongodb.com/docs/database-tools/mongodump.md#mongodb-binary-bin.mongodump) started with [`--oplog`](https://www.mongodb.com/docs/database-tools/mongodump.md#std-option-mongodump.--oplog) fails if a client issues an aggregation pipeline that includes `$out` during the dump process. See [`mongodump --oplog`](https://www.mongodb.com/docs/database-tools/mongodump.md#std-option-mongodump.--oplog) for more information.

### Restrictions

| Restrictions | Description |
| --- | --- |
| [transactions](https://www.mongodb.com/docs/manual/core/transactions.md#std-label-transactions) | An aggregation pipeline cannot use `$out` inside [transactions.](https://www.mongodb.com/docs/manual/core/transactions.md#std-label-transactions) |
| [view definition](https://www.mongodb.com/docs/manual/core/views.md#std-label-views-landing-page) | The `$out` stage is not allowed as part of a view definition. If the view definition includes nested pipeline (e.g. the view definition includes [`$lookup`](https://www.mongodb.com/docs/manual/reference/operator/aggregation/lookup.md#mongodb-pipeline-pipe.-lookup) or [`$facet`](https://www.mongodb.com/docs/manual/reference/operator/aggregation/facet.md#mongodb-pipeline-pipe.-facet) stage), this `$out` 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 | You can't include the `$out` stage in the [`$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) |
| [`$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 `$out` 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 `$out` stage. |
| [`"linearizable"`](https://www.mongodb.com/docs/manual/reference/read-concern-linearizable.md#mongodb-readconcern-readconcern.-linearizable-) read concern | The [`$out`](https://www.mongodb.com/docs/manual/reference/operator/aggregation/out.md#mongodb-pipeline-pipe.-out) 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-). 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 [`$out`](https://www.mongodb.com/docs/manual/reference/operator/aggregation/out.md#mongodb-pipeline-pipe.-out) stage in the pipeline. |

## Examples

### MongoDB Shell

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.

### Output to Same Database

The following aggregation operation filters movies with a runtime greater than 1000 minutes, groups them by release year, and collects their title into an array. The pipeline writes the results to the `movies_by_year` collection in the `sample_mflix` database.

```javascript
db.movies.aggregate( [
    { $match : { runtime : { $gt : 1000 } } },
    { $group : { _id : "$year", movies: { $push: "$title" } } },
    { $out : "movies_by_year" }
] )

```

First Stage (`$match`):

The [`$match`](https://www.mongodb.com/docs/manual/reference/operator/aggregation/match.md#mongodb-pipeline-pipe.-match) stage filters for movies with a `runtime` greater than `1000`.

Second Stage (`$group`):

The [`$group`](https://www.mongodb.com/docs/manual/reference/operator/aggregation/group.md#mongodb-pipeline-pipe.-group) stage groups by the `year` field and uses [`$push`](https://www.mongodb.com/docs/manual/reference/operator/aggregation/push.md#mongodb-group-grp.-push) to add the titles to a `movies` array field.

Third Stage (`$out`):

The `$out` stage outputs the documents to the `movies_by_year` collection in the `sample_mflix` database.

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

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

```

**Output:**

```javascript
[
  { _id: 1978, movies: [ 'Centennial' ] },
  { _id: 1994, movies: [ 'Baseball' ] }
]

```

### Output to a Different Database

**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, `$out` also creates the database.

`$out` can output to a collection in a database different from where you run the aggregation.

The following aggregation operation filters movies with a runtime greater than 1000 minutes, groups them by release year, and collects their title into an array. The pipeline writes the results to the `movies_by_year` collection in the `reporting` database:

```javascript
db.movies.aggregate( [
    { $match : { runtime : { $gt : 1000 } } },
    { $group : { _id : "$year", movies: { $push: "$title" } } },
    { $out : { db: "reporting", coll: "movies_by_year" } }
] )

```

First Stage (`$match`):

The [`$match`](https://www.mongodb.com/docs/manual/reference/operator/aggregation/match.md#mongodb-pipeline-pipe.-match) stage filters for movies with a `runtime` greater than `1000`.

Second Stage (`$group`):

The [`$group`](https://www.mongodb.com/docs/manual/reference/operator/aggregation/group.md#mongodb-pipeline-pipe.-group) stage groups by the `year` field and uses [`$push`](https://www.mongodb.com/docs/manual/reference/operator/aggregation/push.md#mongodb-group-grp.-push) to add the titles to a `movies` array field.

Third Stage (`$out`):

The `$out` stage outputs the documents to the `movies_by_year` collection in the `reporting` database.

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

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

```

**Output:**

```javascript
[
  { _id: 1978, movies: [ 'Centennial' ] },
  { _id: 1994, movies: [ 'Baseball' ] }
]

```
