js and mongoose and I find it somewhat difficult to solve this issue where I have orders schema in my mongodb database, and I want to get top selling products ranked from highest to lowest this is how a document looks like:
so, as it can be seen there is a shopping_cart which is an array of products that can be distinguished by product _id and they each have quantity ( price is not relevant ).I've tried forming this query:
const topselling=Order.aggregate([
{
"$unwind": "$items"
},
{
"$group": {
"_id": "$items.itemId",
"sum": {
"$sum": "$items.qty"
}
}
},
{
"$sort": {
sum: -1
}
},
{
"$group": {
"_id": null,
"top_selling_products ": {
$push: "$_id"
}
}
}
])
console.log(topselling)
But I get an output like this when i console log :
Aggregate {
_pipeline: [
{ '$unwind': '$items' },
{ '$group': [Object] },
{ '$sort': [Object] },
{ '$group': [Object] }
],
_model: Model { Order },
options: {}
}
I expect an output as follows :
[
{
"_id": null,
"top_selling_products ": [
{"title":"carrots","price":100,"imageUrl":"...imageurl"...},
{"title":"Beans","price":200,"imageUrl":"...imageurl"...},
]
}
]
From the Model.aggregate()
documentation, the query is not executed. You have to provide the callback in order to execute it.
Either of these methods should work:
const topselling = Order.aggregate(/* Pipeline */)
.then((res) => {
console.log(res);
})
.catch((err) => {
console.error(err);
});
await
).const topselling = await Order.aggregate(/* Pipeline */);
.exec()
.const topselling = Order.aggregate(/* Pipeline */)
.exec();
While there is something in the $last
group stage as you are pushing ObjectId
but not object into the top_selling_products
array. The last $group
should be:
{
"$group": {
"_id": null,
"top_selling_products": {
$push: "$$ROOT"
}
}
}
With $$ROOT
means the whole document.
Your final output will be:
[
{
"_id": null,
"top_selling_products": [
{ "_id": ObjectId("..."), "sum": 100 },
{ "_id": ObjectId("..."), "sum": 200 }
]
}
]