MongoDB 更新文档在 foreach 循环中失败
Posted
技术标签:
【中文标题】MongoDB 更新文档在 foreach 循环中失败【英文标题】:MongoDB updating the document fails in a foreach loop 【发布时间】:2021-05-31 20:04:05 【问题描述】:我正在开发一个网站,我们在一个 JS 数组中获取每天的订单,如下所示:
let todayOrders = [
order_name: "apple",
order_count: 2
,
order_name: "orange",
order_count: 3
,
order_name: "apple",
order_count: 1
];
我需要将每个订单计数添加到跟踪每个订单的总订单计数文档中。所以我在其中使用了一个 foreach 循环和一个 updateOne
方法,如下所示:
todayOrders.forEach(function(item, index)
Product.updateOne(
product_name: item.order_name
,
$inc: product_count: item1.order_count
,
);
);
问题是这段代码只有在todayOrders
不包含任何重复的order_name
时才能正常工作,在这种情况下它不会应用所有更改。我认为这与 Mongoose 的 async
行为有关。
【问题讨论】:
item1 应该是 item。 跟踪“总”订单需要 $inc 而不是 $set 是的。我对那个不好。 【参考方案1】:您不是在等待您的承诺得到解决,这被认为是可能导致意外行为的不良做法,在您的情况下,它不应该影响预期的逻辑,因为单个文档上的 Mongo 写入运算符是原子的。
但是我仍然建议您重构代码以等待承诺解决,这不能使用 forEach
完成,因为它没有返回值。
这里有一个简单的例子来说明如何做到这一点:
for (const item of todayOrders)
await Product.updateOne(
product_name: item.order_name
,
$inc: product_count: item1.order_count
,
);
或者
// ### 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)
对于并行运行,我建议您使用 bluebird 之类的东西,但是您可以使用 js 原生 Promise 自己完成。
【讨论】:
【参考方案2】:也许对订单进行分组。
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(...)
【讨论】:
以上是关于MongoDB 更新文档在 foreach 循环中失败的主要内容,如果未能解决你的问题,请参考以下文章
如何使用 Node.js 在 MongoDB 中使用 cursor.forEach()?