I want to perform an aggregation query that does basic pagination:
company_id
order_number
100
and passes on the rest2
and passes them onHere is a breakdown of the query:
db.Order.collection.aggregate([
This finds all matching documents:
{ '$match' : { "company_id" : ObjectId("54c0...") } },
This sorts the documents:
{ '$sort' : { 'order_number' : -1 } },
This counts the documents and passes the unmodified documents, but I'm sure doing it wrong, because things turn weird from here:
{
'$group' : {
'_id' : null,
'count' : { '$sum' : 1 },
'entries' : { '$push' : "$$ROOT" }
}
},
This seems to skip some documents:
{ "$skip" : 100 },
This is supposed to limit the documents, but it does not:
{ "$limit" : 2 },
This does return the count, but it does not return the documents in an array, instead it returns arrays with each field:
{ '$project' : {
'count' : 1,
'entries' : {'_id' : "$entries._id", 'order_number' : "$entries.order_number"}
}
}
])
This is the result:
[
{ "_id" : null,
"count" : 300,
"entries" : [
{
"_id" : [ObjectId('5a5c...'), ObjectId('5a5c...')],
"order_number" : ["4346", "4345"]
},
{
"_id" : [ObjectId('5a5c...'), ObjectId('5a5c...')],
"order_number" : ["4346", "4345"]
},
...
]
}
]
Where do I get it wrong?
mongoose-aggregate-paginate is a Mongoose plugin easy to add pagination for aggregates. This plugin can be used in combination with view pagination middleware such as express-paginate.
In MongoDB, aggregation operations process the data records/documents and return computed results. It collects values from various documents and groups them together and then performs different types of operations on that grouped data like sum, average, minimum, maximum, etc to return a computed result.
On large collections of millions of documents, MongoDB's aggregation was shown to be much worse than Elasticsearch. Performance worsens with collection size when MongoDB starts using the disk due to limited system RAM. The $lookup stage used without indexes can be very slow.
To calculate totals and return a subset, you need to apply grouping and skip/limit to the same dataset. For that you can utilise facets
For example to show 3rd page, 10 documents per page:
db.Order.aggregate([
{ '$match' : { "company_id" : ObjectId("54c0...") } },
{ '$sort' : { 'order_number' : -1 } },
{ '$facet' : {
metadata: [ { $count: "total" }, { $addFields: { page: NumberInt(3) } } ],
data: [ { $skip: 20 }, { $limit: 10 } ] // add projection here wish you re-shape the docs
} }
] )
It will return a single document with 2 fields:
{
"metadata" : [
{
"total" : 300,
"page" : 3
}
],
"data" : [
{
... original document ...
},
{
... another document ...
},
{
... etc up to 10 docs ...
}
]
}
Since mongoDB version 5.0 there is another option, that allows to avoid the disadvantage of $facet
, the grouping of all returned document into a one big document. The main concern is that a document as a size limit of 16M. Using $setWindowFields
allows to avoid this concern:
db.Order.aggregate([
{$match: {company_id: ObjectId("54c0...") } },
{$sort: {order_number: -1 } },
{$setWindowFields: {output: {totalCount: {$count: {}}}}}
{$skip: 20 },
{$limit: 10 }
])
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With