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

# $accumulator (accumulator operator)

## Definition

Defines a custom [accumulator operator](https://www.mongodb.com/docs/manual/reference/mql/accumulators.md#std-label-agg-operators-group-accumulators). Accumulators are operators that maintain their state (e.g. totals, maximums, minimums, and related data) as documents progress through the pipeline. Use the [`$accumulator`](https://www.mongodb.com/docs/manual/reference/operator/aggregation/accumulator.md#mongodb-group-grp.-accumulator) operator to execute your own JavaScript functions to implement behavior not supported by the MongoDB Query Language. See also [`$function`.](https://www.mongodb.com/docs/manual/reference/operator/aggregation/function.md#mongodb-expression-exp.-function)

[`$accumulator`](https://www.mongodb.com/docs/manual/reference/operator/aggregation/accumulator.md#mongodb-group-grp.-accumulator) is available in these stages:

- [`$bucket`](https://www.mongodb.com/docs/manual/reference/operator/aggregation/bucket.md#mongodb-pipeline-pipe.-bucket)

- [`$bucketAuto`](https://www.mongodb.com/docs/manual/reference/operator/aggregation/bucketauto.md#mongodb-pipeline-pipe.-bucketAuto)

- [`$group`](https://www.mongodb.com/docs/manual/reference/operator/aggregation/group.md#mongodb-pipeline-pipe.-group)

**Important:**

Executing JavaScript inside of an aggregation operator may decrease performance. Only use the [`$accumulator`](https://www.mongodb.com/docs/manual/reference/operator/aggregation/accumulator.md#mongodb-group-grp.-accumulator) operator if the provided [pipeline operators](https://www.mongodb.com/docs/manual/reference/mql/aggregation-stages.md#std-label-aggregation-pipeline-operator-reference) cannot fulfill your application's needs.

## Syntax

The [`$accumulator`](https://www.mongodb.com/docs/manual/reference/operator/aggregation/accumulator.md#mongodb-group-grp.-accumulator) operator has this syntax:

```javascript
{
  $accumulator: {
    init: <code>,
    initArgs: <array expression>,        // Optional
    accumulate: <code>,
    accumulateArgs: <array expression>,
    merge: <code>,
    finalize: <code>,                    // Optional
    lang: <string>
  }
}
```

| Field | Type | Description |
| --- | --- | --- |
| [init](https://www.mongodb.com/docs/manual/reference/operator/aggregation/accumulator.md#std-label-accumulator-init) | String or Code | Function used to initialize the state. The `init` function receives its arguments from the [initArgs](https://www.mongodb.com/docs/manual/reference/operator/aggregation/accumulator.md#std-label-accumulator-initArgs) array expression. You can specify the function definition as either BSON type Code or String. The `init` function has the following form: `function (<initArg1>, <initArg2>, ...) {
  ...
  return <initialState>
}` Spilling to disk or running a query on a sharded cluster can cause the accumulator to be computed as a merge of multiple sub-accumulations, each of which begins by calling `init()`. Ensure that your `init()`, `accumulate()`, and `merge()` functions are compatible with this execution model. |
| [initArgs](https://www.mongodb.com/docs/manual/reference/operator/aggregation/accumulator.md#std-label-accumulator-initArgs) | Array | Optional. Arguments passed to the `init` function. `initArgs` has the following form: `[ <initArg1>, <initArg2>, ... ]` IMPORTANT: When used in a [`$bucketAuto`](https://www.mongodb.com/docs/manual/reference/operator/aggregation/bucketauto.md#mongodb-pipeline-pipe.-bucketAuto) stage, `initArgs` cannot refer to the group key (i.e., you cannot use the `$<fieldName>` syntax). Instead, in a [`$bucketAuto`](https://www.mongodb.com/docs/manual/reference/operator/aggregation/bucketauto.md#mongodb-pipeline-pipe.-bucketAuto) stage, you can only specify constant values in `initArgs`. |
| [accumulate](https://www.mongodb.com/docs/manual/reference/operator/aggregation/accumulator.md#std-label-accumulator-accumulate) | String or Code | Function used to accumulate documents. The `accumulate` function receives its arguments from the current state and [accumulateArgs](https://www.mongodb.com/docs/manual/reference/operator/aggregation/accumulator.md#std-label-accumulator-accumulateArgs) array expression. The result of the `accumulate` function becomes the new state. You can specify the function definition as either BSON type Code or String. The `accumulate` function has the following form: `function(state, <accumArg1>, <accumArg2>, ...) {
  ...
  return <newState>
}` |
| [accumulateArgs](https://www.mongodb.com/docs/manual/reference/operator/aggregation/accumulator.md#std-label-accumulator-accumulateArgs) | Array | Arguments passed to the `accumulate` function. You can use `accumulateArgs` to specify what field values to pass to the `accumulate` function. `accumulateArgs` has the following form: `[ <accumArg1>, <accumArg2>, ... ]` |
| [merge](https://www.mongodb.com/docs/manual/reference/operator/aggregation/accumulator.md#std-label-accumulator-merge) | String or Code | Function used to merge two internal states. `merge` must be either a String or Code BSON type. `merge` returns the combined result of the two merged states. For information on when the merge function is called, see [Merge Two States with `$merge`.](https://www.mongodb.com/docs/manual/reference/operator/aggregation/accumulator.md#std-label-merge-multiple-states) The `merge` function has the following form: `function (<state1>, <state2>) {
  <logic to merge state1 and state2>
  return <newState>
}` |
| [finalize](https://www.mongodb.com/docs/manual/reference/operator/aggregation/accumulator.md#std-label-accumulator-finalize) | String or Code | Optional. Function used to update the result of the accumulation. The `finalize` function has the following form: `function (state) {
  ...
  return <finalState>
}` |
| [lang](https://www.mongodb.com/docs/manual/reference/operator/aggregation/accumulator.md#std-label-accumulator-lang) | String | The language used in the [`$accumulator`](https://www.mongodb.com/docs/manual/reference/operator/aggregation/accumulator.md#mongodb-group-grp.-accumulator) code. IMPORTANT: Currently, the only supported value for `lang` is `js`. |

## Behavior

The following steps outline how the [`$accumulator`](https://www.mongodb.com/docs/manual/reference/operator/aggregation/accumulator.md#mongodb-group-grp.-accumulator) operator processes documents:

1. The operator begins at an initial state, defined by the [init](https://www.mongodb.com/docs/manual/reference/operator/aggregation/accumulator.md#std-label-accumulator-init) function.

2. For each document, the operator updates the state based on the [accumulate](https://www.mongodb.com/docs/manual/reference/operator/aggregation/accumulator.md#std-label-accumulator-accumulate) function. The [accumulate](https://www.mongodb.com/docs/manual/reference/operator/aggregation/accumulator.md#std-label-accumulator-accumulate) function's first argument is the current state, and additional arguments are be specified in the [accumulateArgs](https://www.mongodb.com/docs/manual/reference/operator/aggregation/accumulator.md#std-label-accumulator-accumulateArgs) array.

3. When the operator needs to merge multiple intermediate states, it executes the [merge](https://www.mongodb.com/docs/manual/reference/operator/aggregation/accumulator.md#std-label-accumulator-merge) function. For more information on when the [merge](https://www.mongodb.com/docs/manual/reference/operator/aggregation/accumulator.md#std-label-accumulator-merge) function is called, see [Merge Two States with `$merge`.](https://www.mongodb.com/docs/manual/reference/operator/aggregation/accumulator.md#std-label-merge-multiple-states)

4. If a [finalize](https://www.mongodb.com/docs/manual/reference/operator/aggregation/accumulator.md#std-label-accumulator-finalize) function has been defined, once all documents have been processed and the state has been updated accordingly, [finalize](https://www.mongodb.com/docs/manual/reference/operator/aggregation/accumulator.md#std-label-accumulator-finalize) converts the state to a final output.

### Merge Two States with `$merge`

As part of its internal operations, the [`$accumulator`](https://www.mongodb.com/docs/manual/reference/operator/aggregation/accumulator.md#mongodb-group-grp.-accumulator) operator may need to merge two separate, intermediate states. The [merge](https://www.mongodb.com/docs/manual/reference/operator/aggregation/accumulator.md#std-label-accumulator-merge) function specifies how the operator should merge two states.

The [merge](https://www.mongodb.com/docs/manual/reference/operator/aggregation/accumulator.md#std-label-accumulator-merge) function always merges two states at a time. If more than two states must be merged, the resulting merge of two states is merged with a single state. This process repeats until all states are merged.

For example, [`$accumulator`](https://www.mongodb.com/docs/manual/reference/operator/aggregation/accumulator.md#mongodb-group-grp.-accumulator) may need to combine two states in the following scenarios:

- [`$accumulator`](https://www.mongodb.com/docs/manual/reference/operator/aggregation/accumulator.md#mongodb-group-grp.-accumulator) is run on a sharded cluster. The operator needs to merge the results from each shard to obtain the final result.

- A single [`$accumulator`](https://www.mongodb.com/docs/manual/reference/operator/aggregation/accumulator.md#mongodb-group-grp.-accumulator) operation exceeds its specified memory limit. If you specify the [`allowDiskUse`](https://www.mongodb.com/docs/manual/reference/method/db.collection.aggregate.md#mongodb-method-db.collection.aggregate) option, the operator stores the in-progress operation on disk and finishes the operation in memory. Once the operation finishes, the results from disk and memory are merged together using the [merge](https://www.mongodb.com/docs/manual/reference/operator/aggregation/accumulator.md#std-label-accumulator-merge) function.

### Document Processing Order

The order that MongoDB processes documents for the `init()`, `accumulate()`, and `merge()` functions can vary, and might differ from the order that those documents are specified to the `$accumulator` function.

For example, consider a series of documents where the `_id` fields are the letters of the alphabet:

```javascript&#xA;
{ _id: 'a' },
{ _id: 'b' },
{ _id: 'c' }
...
{ _id: 'z' }
```

Next, consider an aggregation pipeline that sorts the documents by the `_id` field and then uses an `$accumulator` function to concatenate the `_id` field values:

```javascript
[
   {
      $sort: { _id: 1 }
   },
   {
      $group: {
         _id: null,
         alphabet: {
            $accumulator: {
               init: function() {
                  return ""
               },
               accumulate: function(state, letter) {
                  return(state + letter)
               },
               accumulateArgs: [ "$_id" ],
               merge: function(state1, state2) {
                  return(state1 + state2)
               },
               lang: "js"
            }
         }
      }
   }
]
```

MongoDB does not guarantee that the documents are processed in the sorted order, meaning the `alphabet` field does not necessarily get set to `abc...z`.

Due to this behavior, ensure that your `$accumulator` function does not need to process and return documents in a specific order.

### Javascript Enabled

To use [`$accumulator`](https://www.mongodb.com/docs/manual/reference/operator/aggregation/accumulator.md#mongodb-group-grp.-accumulator), you must have server-side scripting enabled.

If you do not use [`$accumulator`](https://www.mongodb.com/docs/manual/reference/operator/aggregation/accumulator.md#mongodb-group-grp.-accumulator) (or [`$function`](https://www.mongodb.com/docs/manual/reference/operator/aggregation/function.md#mongodb-expression-exp.-function), [`$where`](https://www.mongodb.com/docs/manual/reference/operator/query/where.md#mongodb-query-op.-where), or [`mapReduce`](https://www.mongodb.com/docs/manual/reference/command/mapreduce.md#mongodb-dbcommand-dbcmd.mapReduce)), disable server-side scripting:

- For a [`mongod`](https://www.mongodb.com/docs/manual/reference/program/mongod.md#mongodb-binary-bin.mongod) instance, see [`security.javascriptEnabled`](https://www.mongodb.com/docs/manual/reference/configuration-options.md#mongodb-setting-security.javascriptEnabled) configuration option or [`--noscripting`](https://www.mongodb.com/docs/manual/reference/program/mongod.md#std-option-mongod.--noscripting) command-line option.

- For a [`mongos`](https://www.mongodb.com/docs/manual/reference/program/mongos.md#mongodb-binary-bin.mongos) instance, see [`security.javascriptEnabled`](https://www.mongodb.com/docs/manual/reference/configuration-options.md#mongodb-setting-security.javascriptEnabled) configuration option or the [`--noscripting`](https://www.mongodb.com/docs/manual/reference/program/mongos.md#std-option-mongos.--noscripting) command-line option.

  In earlier versions, MongoDB does not allow JavaScript execution on
  [`mongos`](https://www.mongodb.com/docs/manual/reference/program/mongos.md#mongodb-binary-bin.mongos) instances.

See also [➤ Run MongoDB with Secure Configuration Options.](https://www.mongodb.com/docs/manual/administration/security-checklist.md#std-label-security-checklist-javascript)

### Unsupported Array and String Functions

MongoDB 6.0 upgrades the internal JavaScript engine used for [server-side JavaScript](https://www.mongodb.com/docs/manual/core/server-side-javascript.md#std-label-server-side-javascript), [`$accumulator`](https://www.mongodb.com/docs/manual/reference/operator/aggregation/accumulator.md#mongodb-group-grp.-accumulator), [`$function`](https://www.mongodb.com/docs/manual/reference/operator/aggregation/function.md#mongodb-expression-exp.-function), and [`$where`](https://www.mongodb.com/docs/manual/reference/operator/query/where.md#mongodb-query-op.-where) expressions and from MozJS-60 to MozJS-91. Several deprecated, non-standard array and string functions that existed in MozJS-60 are removed in MozJS-91.

## 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.

### Use `$accumulator` to Implement the `$avg` Operator

**Note:**

This example walks through using the [`$accumulator`](https://www.mongodb.com/docs/manual/reference/operator/aggregation/accumulator.md#mongodb-group-grp.-accumulator) operator to implement the [`$avg`](https://www.mongodb.com/docs/manual/reference/operator/aggregation/avg.md#mongodb-group-grp.-avg) operator, which is already supported by MongoDB. The goal of this example is not to implement new functionality, but to illustrate the behavior and syntax of the [`$accumulator`](https://www.mongodb.com/docs/manual/reference/operator/aggregation/accumulator.md#mongodb-group-grp.-accumulator) operator with familiar logic.

The following operation [`groups`](https://www.mongodb.com/docs/manual/reference/operator/aggregation/group.md#mongodb-pipeline-pipe.-group) the documents by `rated`, and uses [`$accumulator`](https://www.mongodb.com/docs/manual/reference/operator/aggregation/accumulator.md#mongodb-group-grp.-accumulator) to compute the average `imdb.rating` for each content rating. The [`$match`](https://www.mongodb.com/docs/manual/reference/operator/aggregation/match.md#mongodb-pipeline-pipe.-match) stage restricts the input to the `G`, `PG`, `PG-13`, and `R` content ratings, and excludes documents where `imdb.rating` is not a double, such as an empty string:

```javascript
db.movies.aggregate( [
   {
      $match: {
         rated: { $in: [ "G", "PG", "PG-13", "R" ] },
         "imdb.rating": { $type: "double" }
      }
   },
   {
      $group: {
         _id: "$rated",
         avgRating: {
            $accumulator: {
               init: function() {                          // Set the initial state
                  return { count: 0, sum: 0 }
               },

               accumulate: function(state, rating) {       // Define how to update the state
                  return {
                     count: state.count + 1,
                     sum: state.sum + rating
                  }
               },

               accumulateArgs: [ "$imdb.rating" ],         // Argument required by the accumulate function

               merge: function(state1, state2) {           // When the operator performs a merge,
                  return {                                 // add the fields from the two states
                     count: state1.count + state2.count,
                     sum: state1.sum + state2.sum
                  }
               },

               finalize: function(state) {                 // After collecting the results from all documents,
                  return (state.sum / state.count)         // calculate the average
               },
               lang: "js"
            }
         }
      }
   },
   { $sort: { _id: 1 } }
] )

```

**Output:**

```javascript
[
  {
    _id: 'G',
    avgRating: 6.628092243186578
  },
  {
    _id: 'PG',
    avgRating: 6.43525917926564
  },
  {
    _id: 'PG-13',
    avgRating: 6.404911676001717
  },
  {
    _id: 'R',
    avgRating: 6.456657633242984
  }
]

```

#### Behavior

The [`$accumulator`](https://www.mongodb.com/docs/manual/reference/operator/aggregation/accumulator.md#mongodb-group-grp.-accumulator) defines an initial state where `count` and `sum` are both set to `0`. For each document that the [`$accumulator`](https://www.mongodb.com/docs/manual/reference/operator/aggregation/accumulator.md#mongodb-group-grp.-accumulator) processes, it updates the state by:

- Incrementing the `count` by 1 and

- Adding the values of the document's `imdb.rating` field to the `sum`. The [accumulate](https://www.mongodb.com/docs/manual/reference/operator/aggregation/accumulator.md#std-label-accumulator-accumulate) function can access the `imdb.rating` field because it is passed in the [accumulateArgs](https://www.mongodb.com/docs/manual/reference/operator/aggregation/accumulator.md#std-label-accumulator-accumulateArgs) field.

With each document that is processed, the [accumulate](https://www.mongodb.com/docs/manual/reference/operator/aggregation/accumulator.md#std-label-accumulator-accumulate) function returns the updated state.

Once all documents have been processed, the [finalize](https://www.mongodb.com/docs/manual/reference/operator/aggregation/accumulator.md#std-label-accumulator-finalize) function divides the `sum` of the ratings by the `count` of documents to obtain the average. This removes the need to keep a running computed average, since the [finalize](https://www.mongodb.com/docs/manual/reference/operator/aggregation/accumulator.md#std-label-accumulator-finalize) function receives the cumulative `sum` and `count` of all documents.

#### Comparison with `$avg`

This operation is equivalent to the following pipeline, which uses the [`$avg`](https://www.mongodb.com/docs/manual/reference/operator/aggregation/avg.md#mongodb-group-grp.-avg) operator:

```javascript
db.movies.aggregate( [
   {
      $match: {
         rated: { $in: [ "G", "PG", "PG-13", "R" ] },
         "imdb.rating": { $type: "double" }
      }
   },
   {
      $group: {
         _id: "$rated",
         avgRating: { $avg: "$imdb.rating" }
      }
   },
   { $sort: { _id: 1 } }
] )

```

**Output:**

```javascript
[
  {
    _id: 'G',
    avgRating: 6.6280922431865825
  },
  {
    _id: 'PG',
    avgRating: 6.435259179265659
  },
  {
    _id: 'PG-13',
    avgRating: 6.404911676001723
  },
  {
    _id: 'R',
    avgRating: 6.456657633242999
  }
]

```

### Use `initArgs` to Vary the Initial State by Group

You can use the [initArgs](https://www.mongodb.com/docs/manual/reference/operator/aggregation/accumulator.md#std-label-accumulator-initArgs) option to vary the initial state of [`$accumulator`](https://www.mongodb.com/docs/manual/reference/operator/aggregation/accumulator.md#mongodb-group-grp.-accumulator). This can be useful if you want to, for example:

- Use the value of a field which is not in your state to affect your state, or

- Set the initial state to a different value based on the group being processed.

Suppose an application allows users to query this data to find movies. It may be useful to show more results for the content rating that the user prefers. For this example, the user's preferred content rating is `PG-13`, which is passed to the `init` function as `userProfileRated`.

The following aggregation pipeline [`groups`](https://www.mongodb.com/docs/manual/reference/operator/aggregation/group.md#mongodb-pipeline-pipe.-group) the documents by `rated`. The operation uses the [`$accumulator`](https://www.mongodb.com/docs/manual/reference/operator/aggregation/accumulator.md#mongodb-group-grp.-accumulator) to display a different number of movies from each content rating depending on whether the movie's rating matches the rating in the user's profile:

**Note:**

To run this example with a different preferred content rating, replace `"PG-13"` in the [initArgs](https://www.mongodb.com/docs/manual/reference/operator/aggregation/accumulator.md#std-label-accumulator-initArgs) array with another value, such as `"R"`.

```javascript
db.movies.aggregate( [
   {
      $match: {
         rated: { $in: [ "G", "PG", "PG-13", "R" ] },
         "imdb.rating": { $type: "double" }
      }
   },
   {
      $sort: { "imdb.rating": -1, title: 1 }
   },
   {
      $group: {
         _id: { rated: "$rated" },
         movies: {
            $accumulator: {
               init: function(rated, userProfileRated) {    // Set the initial state
                  return {
                     max: rated === userProfileRated ? 3 : 1, // If the group matches the user's rating,
                     movies: []                               // return 3 movies. Otherwise, return 1.
                  }
               },

               initArgs: [ "$rated", "PG-13" ],             // Argument to pass to the init function

               accumulate: function(state, movieTitle) {    // Define how to update the state
                  if (state.movies.length < state.max) {
                     state.movies.push(movieTitle);
                  }
                  return state;
               },

               accumulateArgs: [ "$title" ],                // Argument required by the accumulate function

               merge: function(state1, state2) {
                  return {
                     max: state1.max,
                     movies: state1.movies.concat(state2.movies).slice(0, state1.max)
                  }
               },

               finalize: function(state) {                  // Adjust the state to only return the field we need
                  return state.movies
               },
               lang: "js"
            }
         }
      }
   },
   { $sort: { "_id.rated": 1 } }
] )

```

**Output:**

```javascript
[
  {
    _id: {
      rated: 'G'
    },
    movies: [
      'Modern Times'
    ]
  },
  {
    _id: {
      rated: 'PG'
    },
    movies: [
      'Life'
    ]
  },
  {
    _id: {
      rated: 'PG-13'
    },
    movies: [
      'A Brave Heart: The Lizzie Velasquez Story',
      'The Dark Knight',
      'The Lord of the Rings: The Return of the King'
    ]
  },
  {
    _id: {
      rated: 'R'
    },
    movies: [
      'The Shawshank Redemption'
    ]
  }
]

```

#### Behavior

The [init](https://www.mongodb.com/docs/manual/reference/operator/aggregation/accumulator.md#std-label-accumulator-init) function defines an initial state containing `max` and `movies` fields. The `max` field sets the maximum number of movies for that particular group. If the document's `rated` field matches `userProfileRated`, that group contains a maximum of 3 movies. Otherwise, if the document's `rated` field does not match `userProfileRated`, the group contains at most a single movie. The [init](https://www.mongodb.com/docs/manual/reference/operator/aggregation/accumulator.md#std-label-accumulator-init) function receives both the `rated` and `userProfileRated` arguments from the [initArgs](https://www.mongodb.com/docs/manual/reference/operator/aggregation/accumulator.md#std-label-accumulator-initArgs) array.

For each document that the [`$accumulator`](https://www.mongodb.com/docs/manual/reference/operator/aggregation/accumulator.md#mongodb-group-grp.-accumulator) processes, it pushes the `title` of the movie to the `movies` array, if that title would not put the length of `movies` over the `max` value. With each document that is processed, the [accumulate](https://www.mongodb.com/docs/manual/reference/operator/aggregation/accumulator.md#std-label-accumulator-accumulate) function returns the updated state.

The [merge](https://www.mongodb.com/docs/manual/reference/operator/aggregation/accumulator.md#std-label-accumulator-merge) function defines how to merge two states. The function concatenates the `movies` arrays from each state together, and the length of the resulting array is limited using the [slice()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/slice) method to ensure that it does not exceed the `max` value.

Once all documents have been processed, the [finalize](https://www.mongodb.com/docs/manual/reference/operator/aggregation/accumulator.md#std-label-accumulator-finalize) function modifies the resulting state to only return the titles of the movies. Without this function, the `max` field would also be included in the output, which does not fulfill any needs for the application.
