Aggregation Pipeline Stages in MongoDB

Last Updated : 5 May, 2026

MongoDB’s aggregation pipeline is a framework that processes data in a sequence of stages, where each stage performs a specific operation and passes the transformed result to the next stage.

  • Data flows through multiple stages in a defined order.
  • Each stage performs a specific operation such as filtering, grouping, sorting, or transforming data.
  • The output of one stage becomes the input for the next stage.
  • It allows complex data processing and analysis in a step-by-step manner.
  • Common stages include $match, $group, $sort, $project, and $limit.

Syntax:

db.<collection_name>.aggregate(pipeline, options)
 or 
db.<collection_name>.aggregate( [ { <stage1> }, {<stage2>},... ] )
  • db.<collection_name>: Refers to the collection to work on.
  • .aggregate(): Starts the aggregation process.
  • pipeline: A list of stages (steps) that process the data. Each stage is written inside {}.
  • options: Extra settings (optional) to control the aggregation.
  • [ { <stage1> }, { <stage2> }, ... ]: Stages run in order, one after another.

Aggregation Stages

Aggregation stages are individual steps that work on data to filter, group, or sort it.

1. $addFields Stage

$addFields stage is used to add new fields to the existing documents. It returns documents that contain all the existing fields and newly added fields.

Syntax :

db.<collection_name>.aggregate([
  {
    $addFields: {
      <newField1>: <expression>,
      <newField2>: <expression>
      // ...
    }
  }
])

Example: Add a new field isActive with the value true to every document in the employee_details collection using the MongoDB aggregation pipeline.

db.employee_details.aggregate([
       { 
          $addFields: {"isActive" : true }
       }
])

Output:

Screenshot-2026-02-16-142510

2. $set Stage

$set can overwrite existing fields; however, modifying the _id field is restricted and generally not allowed in most practical scenarios.

Syntax:

db.<collection_name>.aggregate([
  {
    $set: {
      <newField>: <expression>
      // ...
    }
  }
])

Example: Add a new field 'company_name' with the value 'GFG' to every document in the 'employee_details' collection using the MongoDB aggregation pipeline.

db.employee_details.aggregate([
       { 
          $set: {"company_name" : "GFG"}
       }
])

Output:

Screenshot-2026-02-16-142606

Note: $set stage is new stage in version 4.2.

3. $unset Stage

$unset stage is used to remove/exclude fields from the documents. If you want to remove the field or fields from the embedded document then use the dot notation. $unset stage is new staging in version 4.2.

Syntax:

  • To remove a single field, The $unset stage takes a string that specifies the field to remove.
db.<collection_name>.aggregate([
  {
    $unset: "<field>"
  }
])
  • To remove multiple fields, The $unset takes an array of fields to remove.
db.<collection_name>.aggregate([
  {
    $unset: ["<field1>", "<field2>"]
  }
])

Example: Remove the nested field 'address.phone.type' from every document in the 'employee_details' collection using the MongoDB aggregation pipeline.

db.employee_details.aggregate([  
   {
      $unset: "address.phone.type"
   }
])

Output:

Screenshot-2026-02-16-142812

4. $project Stage

$project stage is used to include fields, exclude _id field, add new fields and replace the existing field value in the output document. The following is the table that describes the specification and its description.

SpecificationDescription
field : <1 or true>include the field in the output document.
_id : <0 or false>exclude the _id from the output document.
field : <expression>add the new field or replace the existing field value.
field : <0 or false>excluding any field (except _id) in $project prevents using other inclusion/expression specification.

Syntax:

db.<collection_name>.aggregate([
  {
    $project: {
      <specification>
    }
  }
])

Example: Retrieve only the 'firstName' and 'lastName' fields from the 'name' object and the 'salary' field for every document in the 'employee_details' collection, excluding the '_id field, using the MongoDB aggregation pipeline.

db.employee_details.aggregate(
 [
   {
        $project:{"name.firstName":1, "name.lastName":1, "salary":1, "_id":0}
   }
])

Output:

Screenshot-2026-02-16-142952

5. $count Stage

$count returns the count of the documents present in the selected collection. 

Syntax:

db.<collection_name>.aggregate([
  {
    $count: "<fieldName>"
  }
])

<fieldName> is the name of the output field that stores the count value.

Example: Count the total number of documents in the 'employee_details' collection and return the result as 'employees_count' using the MongoDB aggregation pipeline.

db.employee_details.aggregate(
   [
       {  $count: "employees_count" }
])

Output:

Screenshot-2026-02-16-144145

Note: To get the count of documents in a collection, you can also use db.<collection_name>.countDocuments(). It returns only the count value and does not allow specifying an output field.

6. $unwind Stage

$unwind deconstructs an array field into separate documents. If the field isn’t an array but exists (not null/missing/empty), it’s treated as a single-element array, and includeArrayIndex is set to null.

Syntax:

db.<collection_name>.aggregate(
     [
         {
             $unwind:
             {
                  path: <field path>,
                  includeArrayIndex: <string>,
                  preserveNullAndEmptyArrays: <boolean>
             }
        }
])
  • path: Field path to unwind (e.g., "$skills").
  • includeArrayIndex: Adds the array index to the output; null for non-array values.
  • preserveNullAndEmptyArrays: If true, keeps documents where the field is missing, null, or an empty array (default: false).

Example: Skip the first 3 documents and then unwind the 'skills' array field in each remaining document in the 'employee_details' collection using the MongoDB aggregation pipeline.

db.employee_details.aggregate(
   [
       {$skip : 3},
       { $unwind: "$skills" }
   ]
)

Output:

Screenshot-2026-02-16-144817

Note: $unwind stage does not include documents whose field is missing, null or empty array until you use preserveNullAndEmptyArrays : true

7. $limit Stage

$limit stage is used to limit the number of documents passed to the next stage in pipeline.

Syntax:

db.<collection_name>.aggregate(
    [
        {
           $limit: <positive 64-bit integer> 
       }
 ])

Example: Limit the results to the first 2 documents and then count these documents, returning the result as 'employees_count', using the MongoDB aggregation pipeline.

db.employee_details.aggregate(
  [
      {$limit : 2},
      {$count : "employees_count" }
  ])

Output:

Screenshot-2026-02-16-145029

8. $sort Stage

$sort orders documents by one or more fields, applying sort keys left to right (first by <field1>, then by <field2> for ties).

Syntax:

db.<collection_name>.aggregate(
   [
       { $sort: { <field1>: <sort order>, <field2>: <sort order> ... } }
 ])

<field> represents the document field on the basis of which we sort the document either ascending or descending depends on the <sort-order>. <sort order> has the following values :

ValueOrder
1 Ascending 
-1Descending

Example of $sort in Ascending Order

Sort the documents in the 'employee_details' collection in ascending order based on the 'firstName' field in the 'name' object using the MongoDB aggregation pipeline.

db.employee_details.aggregate(
  [
      {$sort : {"name.firstName" : 1}}
  ])

Output:

Screenshot-2026-02-16-150326

Example of $sort in Descending Order

Sort the documents in the 'employee_details' collection in descending order based on the 'firstName' field in the 'name' object using the MongoDB aggregation pipeline.

db.employee_details.aggregate(
    [
      {$sort : {"name.firstName" : -1}}
  ])

Output:

Screenshot-2026-02-16-150514

Note: You can sort a maximum of 32 keys.

9. $sortByCount Stage

$sortByCount groups documents by a field, counts each group, and returns the results sorted by count in descending order.

Syntax: 

db.<collection_name>.aggregate(
   [
       {$sortByCount : "<field path>"}
])

Example: Create a MongoDB aggregation pipeline to list and count the occurrences of each skill across all employees in the employee_details collection after unwinding the skills array field.

db.employee_details.aggregate(
   [
      {$unwind : "$skills"},
      {$sortByCount : "$skills"}
  ])

Output:

Screenshot-2026-02-16-153435

Note: $sortByCount is equivalent to applying $group with { $sum: 1 } followed by $sort in descending order of the count.

10. $skip Stage

$skip stage is used to skip the number of documents and passes the remaining documents to the next stage in the pipeline. It returns the remaining documents.

Syntax:

db.<collection_name>.aggregate(
   [ 
       { $skip: <positive 64-bit integer> }
  ])

Example: Skip the first 3 documents in the 'employee_details' collection using the MongoDB aggregation pipeline.

db.employee_details.aggregate(
    [
      {$skip : 3}
  ])

Output:

Screenshot-2026-02-16-151017
Comment
Article Tags:

Explore