$sort, $limit, $skip — order matters
$limit$match$skip$sort
These behave like their find() counterparts, with one difference that matters far more in a pipeline: they are stages, so their position changes the result. $limit before $sort is a different query from $sort before $limit.
{
$sort: {
createdAt: -1
}
}
Multiple fields:
{
$sort: {
userId: 1,
createdAt: -1
}
}
$limit and $skip
{
$limit: 10
}
{
$skip: 20
}
Example:
db.orders.aggregate([
{
$match: {
status: "completed"
}
},
{
$sort: {
createdAt: -1
}
},
{
$skip: 20
},
{
$limit: 10
}
])
⚠️ Order Matters
This:
$sort
↓
$limit
means:
Find the top 10 after sorting.
But:
$limit
↓
$sort
means:
Take the first 10 arbitrary/current-order documents, then sort only those 10.
Aggregation is a pipeline.
Every stage receives the output of the previous stage.
This sounds obvious, but it is one of the biggest sources of mistakes.