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

# $bucket (aggregation stage)

## Definition

Categorizes incoming documents into groups, called buckets, based on a specified expression and bucket boundaries and outputs a document per each bucket. Each output document contains an `_id` field whose value specifies the inclusive lower bound of the bucket. The [output](https://www.mongodb.com/docs/manual/reference/operator/aggregation/bucket.md#std-label-bucket-output) option specifies the fields included in each output document.

[`$bucket`](https://www.mongodb.com/docs/manual/reference/operator/aggregation/bucket.md#mongodb-pipeline-pipe.-bucket) only produces output documents for buckets that contain at least one input document.

## Considerations

### `$bucket` and Memory Restrictions

The [`$bucket`](https://www.mongodb.com/docs/manual/reference/operator/aggregation/bucket.md#mongodb-pipeline-pipe.-bucket) stage has a limit of 100 megabytes of RAM. By default, if the stage exceeds this limit, [`$bucket`](https://www.mongodb.com/docs/manual/reference/operator/aggregation/bucket.md#mongodb-pipeline-pipe.-bucket) returns an error. To allow more space for stage processing, use the [allowDiskUse](https://www.mongodb.com/docs/manual/reference/command/aggregate.md#std-label-aggregate-cmd-allowDiskUse) option to enable aggregation pipeline stages to write data to temporary files.

**See also:**

[Aggregation Pipeline Limits](https://www.mongodb.com/docs/manual/core/aggregation-pipeline-limits.md#std-label-agg-pipeline-limits)

## Syntax

```javascript
{
  $bucket: {
      groupBy: <expression>,
      boundaries: [ <lowerbound1>, <lowerbound2>, ... ],
      default: <literal>,
      output: {
         <output1>: { <$accumulator expression> },
         ...
         <outputN>: { <$accumulator expression> }
      }
   }
}
```

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

| Field | Type | Description |
| --- | --- | --- |
| [groupBy](https://www.mongodb.com/docs/manual/reference/operator/aggregation/bucket.md#std-label-bucket-group-by) | expression | An [expression](https://www.mongodb.com/docs/manual/reference/mql/expressions.md#std-label-aggregation-expressions) to group documents by. To specify a [field path](https://www.mongodb.com/docs/manual/core/aggregation-pipeline.md#std-label-agg-quick-ref-field-paths), prefix the field name with a dollar sign `$` and enclose it in quotes. Unless [`$bucket`](https://www.mongodb.com/docs/manual/reference/operator/aggregation/bucket.md#mongodb-pipeline-pipe.-bucket) includes a [default](https://www.mongodb.com/docs/manual/reference/operator/aggregation/bucket.md#std-label-bucket-default) specification, each input document must resolve the `groupBy` field path or expression to a value that falls within one of the ranges specified by the [boundaries.](https://www.mongodb.com/docs/manual/reference/operator/aggregation/bucket.md#std-label-bucket-boundaries) |
| [boundaries](https://www.mongodb.com/docs/manual/reference/operator/aggregation/bucket.md#std-label-bucket-boundaries) | array | An array of values based on the [groupBy](https://www.mongodb.com/docs/manual/reference/operator/aggregation/bucket.md#std-label-bucket-group-by) expression that specify the boundaries for each bucket. Each adjacent pair of values acts as the inclusive lower boundary and the exclusive upper boundary for the bucket. You must specify at least two boundaries. The specified values must be in ascending order and all of the same [type](https://www.mongodb.com/docs/manual/reference/bson-types.md#std-label-bson-types). The exception is if the values are of mixed numeric types, such as: `[ 10, Long(20), Int32(30) ]` For example, an array of `[ 0, 5, 10 ]` creates two buckets: [0, 5) with inclusive lower bound `0` and exclusive upper bound `5`.; [5, 10) with inclusive lower bound `5` and exclusive upper bound `10`. | | [default](https://www.mongodb.com/docs/manual/reference/operator/aggregation/bucket.md#std-label-bucket-default) | literal | Optional. A literal that specifies the `_id` of an additional bucket that contains all documents whose [groupBy](https://www.mongodb.com/docs/manual/reference/operator/aggregation/bucket.md#std-label-bucket-group-by) expression result does not fall into a bucket specified by [boundaries.](https://www.mongodb.com/docs/manual/reference/operator/aggregation/bucket.md#std-label-bucket-boundaries) If unspecified, each input document must resolve the `groupBy` expression to a value within one of the bucket ranges specified by `boundaries` or the operation throws an error. The `default` value must be less than the lowest `boundaries` value, or greater than or equal to the highest `boundaries` value. The `default` value can be of a different [type](https://www.mongodb.com/docs/manual/reference/bson-types.md#std-label-bson-types) than the entries in `boundaries`. |
| [output](https://www.mongodb.com/docs/manual/reference/operator/aggregation/bucket.md#std-label-bucket-output) | document | Optional. A document that specifies the fields to include in the output documents in addition to the `_id` field. To specify the field to include, you must use [accumulator expressions.](https://www.mongodb.com/docs/manual/reference/mql/accumulators.md#std-label-agg-quick-reference-accumulators) `<outputfield1>: { <accumulator>: <expression1> },
...
<outputfieldN>: { <accumulator>: <expressionN> }` If you do not specify an `output` document, the operation returns a `count` field containing the number of documents in each bucket. If you specify an `output` document, only the fields specified in the document are returned; i.e. the `count` field is not returned unless it is explicitly included in the `output` document. |

## Behavior

[`$bucket`](https://www.mongodb.com/docs/manual/reference/operator/aggregation/bucket.md#mongodb-pipeline-pipe.-bucket) requires at least one of the following conditions to be met or the operation throws an error:

- Each input document resolves the [groupBy](https://www.mongodb.com/docs/manual/reference/operator/aggregation/bucket.md#std-label-bucket-group-by) expression to a value within one of the bucket ranges specified by [boundaries](https://www.mongodb.com/docs/manual/reference/operator/aggregation/bucket.md#std-label-bucket-boundaries), or

- A [default](https://www.mongodb.com/docs/manual/reference/operator/aggregation/bucket.md#std-label-bucket-default) value is specified to bucket documents whose `groupBy` values are outside of the `boundaries` or of a different [BSON type](https://www.mongodb.com/docs/manual/reference/bson-types.md#std-label-bson-types) than the values in `boundaries`.

If the `groupBy` expression resolves to an array or a document, `$bucket` arranges the input documents into buckets using the comparison logic from [`$sort`.](https://www.mongodb.com/docs/manual/reference/operator/aggregation/sort.md#mongodb-pipeline-pipe.-sort)

## Examples

### MongoDB Shell

### Bucket by Year and Filter by Bucket Results

In [`mongosh`](https://www.mongodb.com/docs/mongodb-shell.md#mongodb-binary-bin.mongosh), create a sample collection named `artists` with the following documents:

```javascript
db.artists.insertMany([
  { "_id" : 1, "last_name" : "Bernard", "first_name" : "Emil", "year_born" : 1868, "year_died" : 1941, "nationality" : "France" },
  { "_id" : 2, "last_name" : "Rippl-Ronai", "first_name" : "Joszef", "year_born" : 1861, "year_died" : 1927, "nationality" : "Hungary" },
  { "_id" : 3, "last_name" : "Ostroumova", "first_name" : "Anna", "year_born" : 1871, "year_died" : 1955, "nationality" : "Russia" },
  { "_id" : 4, "last_name" : "Van Gogh", "first_name" : "Vincent", "year_born" : 1853, "year_died" : 1890, "nationality" : "Holland" },
  { "_id" : 5, "last_name" : "Maurer", "first_name" : "Alfred", "year_born" : 1868, "year_died" : 1932, "nationality" : "USA" },
  { "_id" : 6, "last_name" : "Munch", "first_name" : "Edvard", "year_born" : 1863, "year_died" : 1944, "nationality" : "Norway" },
  { "_id" : 7, "last_name" : "Redon", "first_name" : "Odilon", "year_born" : 1840, "year_died" : 1916, "nationality" : "France" },
  { "_id" : 8, "last_name" : "Diriks", "first_name" : "Edvard", "year_born" : 1855, "year_died" : 1930, "nationality" : "Norway" }
])
```

The following operation groups the documents into buckets according to the `year_born` field and filters based on the count of documents in the buckets:

```javascript
 db.artists.aggregate( [
 // First Stage
 {
   $bucket: {
     groupBy: "$year_born",                        // Field to group by
     boundaries: [ 1840, 1850, 1860, 1870, 1880 ], // Boundaries for the buckets
     default: "Other",                             // Bucket ID for documents which do not fall into a bucket
     output: {                                     // Output for each bucket
       "count": { $sum: 1 },
       "artists" :
         {
           $push: {
             "name": { $concat: [ "$first_name", " ", "$last_name"] },
             "year_born": "$year_born"
           }
         }
     }
   }
 },
 // Second Stage
 {
   $match: { count: {$gt: 3} }
 }
] )
```

First Stage

The [`$bucket`](https://www.mongodb.com/docs/manual/reference/operator/aggregation/bucket.md#mongodb-pipeline-pipe.-bucket) stage groups the documents into buckets by the `year_born` field. The buckets have the following [boundaries:](https://www.mongodb.com/docs/manual/reference/operator/aggregation/bucket.md#std-label-bucket-boundaries)

- \[1840, 1850) with inclusive lowerbound `1840` and exclusive upper bound `1850`. - \[1850, 1860) with inclusive lowerbound `1850` and exclusive upper bound `1860`. - \[1860, 1870) with inclusive lowerbound `1860` and exclusive upper bound `1870`. - \[1870, 1880) with inclusive lowerbound `1870` and exclusive upper bound `1880`. - If a document did not contain the `year_born` field or its `year_born` field was outside the ranges above, it would be placed in the [default](https://www.mongodb.com/docs/manual/reference/operator/aggregation/bucket.md#std-label-bucket-default) bucket with the `_id` value `"Other"`.

The stage includes the [output](https://www.mongodb.com/docs/manual/reference/operator/aggregation/bucket.md#std-label-bucket-output) document to determine the fields to return:

| Field | Description |
| --- | --- |
| `_id` | Inclusive lower bound of the bucket. |
| `count` | Count of documents in the bucket. |
| `artists` | Array of documents containing information on each artist in the bucket. Each document contains the artist's `name`, which is a concatenation (i.e. [`$concat`](https://www.mongodb.com/docs/manual/reference/operator/aggregation/concat.md#mongodb-expression-exp.-concat)) of the artist's `first_name` and `last_name`.; `year_born` |

This stage passes the following documents to the next stage:

```javascript
{ "_id" : 1840, "count" : 1, "artists" : [ { "name" : "Odilon Redon", "year_born" : 1840 } ] }

{ "_id" : 1850, "count" : 2, "artists" : [ { "name" : "Vincent Van Gogh", "year_born" : 1853 },
                                            { "name" : "Edvard Diriks", "year_born" : 1855 } ] }

{ "_id" : 1860, "count" : 4, "artists" : [ { "name" : "Emil Bernard", "year_born" : 1868 },
                                            { "name" : "Joszef Rippl-Ronai", "year_born" : 1861 },
                                            { "name" : "Alfred Maurer", "year_born" : 1868 },
                                            { "name" : "Edvard Munch", "year_born" : 1863 } ] }

{ "_id" : 1870, "count" : 1, "artists" : [ { "name" : "Anna Ostroumova", "year_born" : 1871 } ] }
```

Second Stage

The [`$match`](https://www.mongodb.com/docs/manual/reference/operator/aggregation/match.md#mongodb-pipeline-pipe.-match) stage filters the output from the previous stage to only return buckets which contain more than 3 documents.

The operation returns the following document:

```javascript
{ "_id" : 1860, "count" : 4, "artists" :
  [
    { "name" : "Emil Bernard", "year_born" : 1868 },
    { "name" : "Joszef Rippl-Ronai", "year_born" : 1861 },
    { "name" : "Alfred Maurer", "year_born" : 1868 },
    { "name" : "Edvard Munch", "year_born" : 1863 }
  ]
}
```

### Use $bucket with $facet to Bucket by Multiple Fields

You can use the [`$facet`](https://www.mongodb.com/docs/manual/reference/operator/aggregation/facet.md#mongodb-pipeline-pipe.-facet) stage to perform multiple [`$bucket`](https://www.mongodb.com/docs/manual/reference/operator/aggregation/bucket.md#mongodb-pipeline-pipe.-bucket) aggregations in a single stage.

In [`mongosh`](https://www.mongodb.com/docs/mongodb-shell.md#mongodb-binary-bin.mongosh), create a sample collection named `artwork` with the following documents:

```javascript
db.artwork.insertMany([
  { "_id" : 1, "title" : "The Pillars of Society", "artist" : "Grosz", "year" : 1926,
      "price" : Decimal128("199.99") },
  { "_id" : 2, "title" : "Melancholy III", "artist" : "Munch", "year" : 1902,
      "price" : Decimal128("280.00") },
  { "_id" : 3, "title" : "Dancer", "artist" : "Miro", "year" : 1925,
      "price" : Decimal128("76.04") },
  { "_id" : 4, "title" : "The Great Wave off Kanagawa", "artist" : "Hokusai",
      "price" : Decimal128("167.30") },
  { "_id" : 5, "title" : "The Persistence of Memory", "artist" : "Dali", "year" : 1931,
      "price" : Decimal128("483.00") },
  { "_id" : 6, "title" : "Composition VII", "artist" : "Kandinsky", "year" : 1913,
      "price" : Decimal128("385.00") },
  { "_id" : 7, "title" : "The Scream", "artist" : "Munch", "year" : 1893
      /* No price*/ },
  { "_id" : 8, "title" : "Blue Flower", "artist" : "O'Keefe", "year" : 1918,
      "price" : Decimal128("118.42") }
])
```

The following operation uses two [`$bucket`](https://www.mongodb.com/docs/manual/reference/operator/aggregation/bucket.md#mongodb-pipeline-pipe.-bucket) stages within a [`$facet`](https://www.mongodb.com/docs/manual/reference/operator/aggregation/facet.md#mongodb-pipeline-pipe.-facet) stage to create two groupings, one by `price` and the other by `year`:

```javascript
db.artwork.aggregate( [
  {
    $facet: {                               // Top-level $facet stage
      "price": [                            // Output field 1
        {
          $bucket: {
              groupBy: "$price",            // Field to group by
              boundaries: [ 0, 200, 400 ],  // Boundaries for the buckets
              default: "Other",             // Bucket ID for documents which do not fall into a bucket
              output: {                     // Output for each bucket
                "count": { $sum: 1 },
                "artwork" : { $push: { "title": "$title", "price": "$price" } },
                "averagePrice": { $avg: "$price" }
              }
          }
        }
      ],
      "year": [                                      // Output field 2
        {
          $bucket: {
            groupBy: "$year",                        // Field to group by
            boundaries: [ 1890, 1910, 1920, 1940 ],  // Boundaries for the buckets
            default: "Unknown",                      // Bucket ID for documents which do not fall into a bucket
            output: {                                // Output for each bucket
              "count": { $sum: 1 },
              "artwork": { $push: { "title": "$title", "year": "$year" } }
            }
          }
        }
      ]
    }
  }
] )
```

First Facet

The first facet groups the input documents by `price`. The buckets have the following boundaries:

- \[0, 200) with inclusive lowerbound `0` and exclusive upper bound `200`. - \[200, 400) with inclusive lowerbound `200` and exclusive upper bound `400`. - "Other", the `default` bucket containing documents without prices or prices outside the ranges above. The [`$bucket`](https://www.mongodb.com/docs/manual/reference/operator/aggregation/bucket.md#mongodb-pipeline-pipe.-bucket) stage includes the [output](https://www.mongodb.com/docs/manual/reference/operator/aggregation/bucket.md#std-label-bucket-output) document to determine the fields to return:

| Field | Description |
| --- | --- |
| `_id` | Inclusive lower bound of the bucket. |
| `count` | Count of documents in the bucket. |
| `artwork` | Array of documents containing information on each artwork in the bucket. |
| `averagePrice` | Employs the [`$avg`](https://www.mongodb.com/docs/manual/reference/operator/aggregation/avg.md#mongodb-group-grp.-avg) operator to display the average price of all artwork in the bucket. |

Second Facet

The second facet groups the input documents by `year`. The buckets have the following boundaries:

- \[1890, 1910) with inclusive lowerbound `1890` and exclusive upper bound `1910`. - \[1910, 1920) with inclusive lowerbound `1910` and exclusive upper bound `1920`. - \[1920, 1940) with inclusive lowerbound `1910` and exclusive upper bound `1940`. - "Unknown", the `default` bucket containing documents without years or years outside the ranges above. The [`$bucket`](https://www.mongodb.com/docs/manual/reference/operator/aggregation/bucket.md#mongodb-pipeline-pipe.-bucket) stage includes the [output](https://www.mongodb.com/docs/manual/reference/operator/aggregation/bucket.md#std-label-bucket-output) document to determine the fields to return:

| Field | Description |
| --- | --- |
| `count` | Count of documents in the bucket. |
| `artwork` | Array of documents containing information on each artwork in the bucket. |

Output

The operation returns the following document:

```javascript
 {
  "price" : [ // Output of first facet
    {
      "_id" : 0,
      "count" : 4,
      "artwork" : [
        { "title" : "The Pillars of Society", "price" : Decimal128("199.99") },
        { "title" : "Dancer", "price" : Decimal128("76.04") },
        { "title" : "The Great Wave off Kanagawa", "price" : Decimal128("167.30") },
        { "title" : "Blue Flower", "price" : Decimal128("118.42") }
      ],
      "averagePrice" : Decimal128("140.4375")
    },
    {
      "_id" : 200,
      "count" : 2,
      "artwork" : [
        { "title" : "Melancholy III", "price" : Decimal128("280.00") },
        { "title" : "Composition VII", "price" : Decimal128("385.00") }
      ],
      "averagePrice" : Decimal128("332.50")
    },
    {
      // Includes documents without prices and prices greater than 400
      "_id" : "Other",
      "count" : 2,
      "artwork" : [
        { "title" : "The Persistence of Memory", "price" : Decimal128("483.00") },
        { "title" : "The Scream" }
      ],
      "averagePrice" : Decimal128("483.00")
    }
  ],
  "year" : [ // Output of second facet
    {
      "_id" : 1890,
      "count" : 2,
      "artwork" : [
        { "title" : "Melancholy III", "year" : 1902 },
        { "title" : "The Scream", "year" : 1893 }
      ]
    },
    {
      "_id" : 1910,
      "count" : 2,
      "artwork" : [
        { "title" : "Composition VII", "year" : 1913 },
        { "title" : "Blue Flower", "year" : 1918 }
      ]
    },
    {
      "_id" : 1920,
      "count" : 3,
      "artwork" : [
        { "title" : "The Pillars of Society", "year" : 1926 },
        { "title" : "Dancer", "year" : 1925 },
        { "title" : "The Persistence of Memory", "year" : 1931 }
      ]
    },
    {
      // Includes documents without a year
      "_id" : "Unknown",
      "count" : 1,
      "artwork" : [
        { "title" : "The Great Wave off Kanagawa" }
      ]
    }
  ]
}
```

## Learn More

To learn more about related pipeline stages, see the [`$bucketAuto`](https://www.mongodb.com/docs/manual/reference/operator/aggregation/bucketauto.md#mongodb-pipeline-pipe.-bucketAuto) guide.
