Reputation: 559
I'm working on a website which we get every day's order in a JS array like this:
let todayOrders = [
{
order_name: "apple",
order_count: 2
},
{
order_name: "orange",
order_count: 3
},
{
order_name: "apple",
order_count: 1
}
];
I need to add every order count to the total order count document which keeps track of every order. So I used a foreach loop and an updateOne
method inside it like this:
todayOrders.forEach(function(item, index){
Product.updateOne(
{
product_name: item.order_name
},
{
$inc: {product_count: item1.order_count}
},
);
});
The problem is this code only works fine if the todayOrders
does not contain any duplicate order_name
which in that case it does not apply all the changes. I believe it has something to do with the async
behavior of Mongoose.
Upvotes: 2
Views: 1165
Reputation: 22296
You are not waiting for your promises to resolve, this is considered bad practice that could lead to unexpected behaviour, in your case it should not affect the intended logic as Mongo write operators on a single document are atomic.
However I still do recommend you refactor your code to wait until the promise resolves, this can't be done with forEach
due to it not having a return value.
Here is a quick example of how you can do it:
for (const item of todayOrders) {
await Product.updateOne(
{
product_name: item.order_name
},
{
$inc: {product_count: item1.order_count}
},
);
}
Or
// ### This is not recommended as it not limited by scale and can cause the app to run out of memory and crash ###
const promises = [];
todayOrders.forEach(function(item, index){
promises.push(Product.updateOne(
{
product_name: item.order_name
},
{
$inc: {product_count: item.order_count}
},
))
});
await Promise.all(promises)
For parallel running I recommend you use something like bluebird, however you can do it yourself with js native promise.
Upvotes: 2
Reputation: 372
Maybe group the orders.
todayOrders.reduce((acc,item)=>{
const index = acc.map(i=>i.order_name).indexOf(item.order_name);
if(index === -1)
acc.push(item);
else
acc[index].order_count += item.order_count;
return acc;
},[]).forEach(...)
Upvotes: 1