🍃 MongoDB Tutorial

MongoDB Aggregation: $sort, $skip, $limit, $unwind and $out Stages

Learn the remaining MongoDB aggregation pipeline stages — $sort, $skip, $limit for ordering and paging results, $unwind for arrays, and $out to save results to a new collection.

$sort, $skip, $limit, $unwind and $out

$sort

Reorders the documents flowing through the pipeline — works the same as find().sort().

db.employees.aggregate([
  { $project: { name: 1, email: 1 } },
  { $sort: { name: 1 } }
])

db.employees.aggregate([
  { $group: { _id: "$age", sumCity: { $sum: 1 } } },
  { $sort: { sumCity: -1 } }
])
// sort by a value computed earlier in the SAME pipeline

$skip

db.employees.aggregate([
  { $match: { gender: "F" } },
  { $skip: 1 }
])

$limit

db.employees.aggregate([
  { $match: { gender: "M" } },
  { $project: { name: 1 } },
  { $limit: 2 }
])

$sort, $skip and $limit combine inside a pipeline the same way they do with find() — for paging aggregated results.

$unwind

Arrays can't be worked with directly by stages like $group. $unwind "flattens" an array field by outputting one copy of the document per array element.

If empid: 202 has lang: ["Hindi", "English"], unwinding lang turns that single document into two: one with lang: "Hindi", one with lang: "English" (every other field stays the same on both copies).

db.employees.aggregate([
  { $match: { empid: 202 } },
  { $unwind: "$lang" }
])

db.employees.aggregate([
  { $match: { empid: 202 } },
  { $unwind: "$deptwork" }
])

This is usually the step right before a $group that needs to tally up individual array elements (e.g. "how many employees speak each language?").

$out — Save Results to a New Collection

Writes the final pipeline output into a brand-new (or existing, after dropping it) collection instead of just returning it. $out must be the last stage in the pipeline.

db.employees.aggregate([
  { $match: { gender: "F" } },
  { $out: "femaleEmp" }
])

show collections
db.femaleEmp.find()
db.employees.aggregate([
  { $group: { _id: "$age", sumAge: { $sum: 1 } } },
  { $out: "sameAgeCount" }
])

Common Errors & Troubleshooting

  • $unwind on a document with an empty array removes it entirely — by default, a document whose array field is [] or missing disappears from the pipeline after $unwind; pass { path: "$field", preserveNullAndEmptyArrays: true } if you need to keep those documents.
  • $out overwriting an existing collection without warning — $out replaces the target collection's entire contents if it already exists — always double-check the target name before running it in production.
  • $sort inside the pipeline needing a lot of memory on huge datasets — sorting a very large intermediate result can hit MongoDB's in-memory sort limit; add an index that supports the sort, or sort earlier in the pipeline on a smaller intermediate result.

Key Takeaways

  • $unwind is the bridge between array fields and stages like $group that can't reach inside arrays directly.
  • $sort/$skip/$limit work the same inside an aggregation pipeline as they do chained onto find().
  • $out persists your aggregation result as a real collection — but it must be the final stage.