$project, $sort, $limit
Reshape output fields with $project, order results with $sort, and cap them with $limit and $skip.
$project: Reshaping Documents
$project controls which fields appear in the output, exactly like find()'s projection argument, but with far more power — it can also compute entirely new fields from expressions.
db.orders.aggregate([ { $project: { customerId: 1, total: 1, _id: 0 } },]);Computing New Fields with $project
db.orders.aggregate([ { $project: { customerId: 1, total: 1, totalWithTax: { $multiply: ["$total", 1.08] }, isLargeOrder: { $gt: ["$total", 100] }, }, },]);Beyond $multiply and $gt shown here, MongoDB's aggregation expressions include string manipulation ($concat, $toUpper), date extraction ($year, $month), conditionals ($cond), and dozens more — covering most computation needs directly in the pipeline.
$sort
$sort orders documents flowing through the pipeline, using the same 1/-1 convention as find().sort().
db.orders.aggregate([ { $group: { _id: "$customerId", totalSpent: { $sum: "$total" } } }, { $sort: { totalSpent: -1 } }, // highest spenders first]);$limit and $skip
$limit caps the number of documents passed to the next stage; $skip discards a number of leading documents — together enabling pagination within a pipeline.
db.orders.aggregate([ { $group: { _id: "$customerId", totalSpent: { $sum: "$total" } } }, { $sort: { totalSpent: -1 } }, { $skip: 10 }, { $limit: 10 }, // "page 2" of top spenders]);FAQs
Yes — placing $limit before $sort would cap the documents before they're ordered, likely giving the wrong result; always $sort before $limit when you want the top N by some criteria.
Yes — $project (or a later stage) can reshape or drop any field present at that point in the pipeline, including ones computed by earlier stages.
Summary
$project reshapes and computes fields, while $sort/$limit/$skip control ordering and pagination of pipeline output. Next, you'll learn $lookup, MongoDB's equivalent of a relational join.