猫鼬-如何以每位一个值更新许多特定记录?

时间:2019-01-05 23:28:57

标签: node.js mongoose

如何在NodeJS-Express中使用猫鼬更新多条记录,每条记录都具有唯一的值(各项都不具有相同的值)而不会引起N + 1问题?我有以下情况:

产品:

[
{
 _id: "407f191e810c19729de860ea",
 title: "....",
 in_stock: 100,
 },
{
 _id: "507f1f77bcf86cd799439011",
 title: "....",
 in_stock: 100,
 },
....
]

然后给出这样的“订单”请求:

[
 {
  item_id: "507f1f77bcf86cd799439011",
  quantity: 5
 },
 {
  item_id: "407f191e810c19729de860ea",
  quantity: 8
 },
...
]

换句话说,给定一个id,quantity tuples数组,我需要减少数据库中每个对应记录的库存。如何做到而不必对每个项目运行一个查询?

在上面的示例中,数据库中的最终结果应为:

[
{
 _id: "407f191e810c19729de860ea",
 title: "....",
 in_stock: 92,
 },
{
 _id: "507f1f77bcf86cd799439011",
 title: "....",
 in_stock: 95,
 },
....
]

3 个答案:

答案 0 :(得分:2)

好吧,在这种情况下,您可以使用类似这样的代码。但我高度怀疑这是您要实现的目标。

我也曾在项目中尝试过相同的问题,但遇到的唯一方法是按id进行迭代并仅运行不同的查询。

db.Element.update(
       { _id: { $in: ['id1', 'id2', 'id3'] } },
       { $set: { visibility : yourvisibility } }
    )

这样的代码应该可以解决问题

updateById(0); //call updates iteration

function updateById(i) {
if (i < order.length) {
    Products.findByIdAndUpdate({ _id: order[i]._id }, { in_stock: order[i].in_stock }, (err, data) => {
        if (!err) { updateById(i++); }
        else{throw err}
    });
}
else {
    // return 
}

}

答案 1 :(得分:2)

您将需要使用id遍历订单数组查找库存中的商品,然后可以更新库存数,例如

order.forEach((item) => {
  Products.findByIdandUpdate(item._id, 
    {$set: {in_stock: (in_stock - item.quantity)}}, {new:true})
    .then((updatedItem) => {
      if(!updatedItem) {
        console.log('Cannot update!');
      }
      else {
       console.log(updatedItem);
      }
 });
});

答案 2 :(得分:1)

对于那些遇到此问题的人,我尚未找到针对此问题的非N + 1解决方案。为了扩展上述答案,我发现的最佳解决方案是使用异步模块,至少避免潜在的阻塞代码:

itemModel.find({ // find items from ids
    '_id': itemIds
}).then(function (items) {
    if (items) {
        asyncModule.each(items,
            function (item, callback) {
                item.in_stock -= orderQuantities[item._id];
                item.save();
                callback(); // tell async that current object is done processing
            }, onCompleteFunc);
    }
}).catch(handleError);

如果有人对此解决方案有任何意见或改进建议,欢迎反馈。