我想在mongodb中增加许多文档

时间:2018-09-26 11:48:16

标签: node.js express mongoose

router.put('/stockAccepted/:id', (req, res, next) =>{    
    stockSchema.findOneAndUpdate({_id: req.params.id}, {
        $set:{
            stockAccepted: req.body.stockAccepted
        }
    },(err, result) => {
        if(err) res.json(err);
        else res.json(result);
    });

    let stockItem = req.body.stockItem;
    stockItem.forEach((element) => {
        console.log("counter")
        productSchema.update({_id: element.productId}, { 
            $inc:{ 
                productQuantity: element.productQuantity
            } 
        }
        ,(err, result) => {
            if(err) res.json(err);
            else res.json(result);
        });        
    });

});

实现它的最佳方法是什么? 此代码将引发错误,指出“标题已发送”。 如何正确实现呢?

2 个答案:

答案 0 :(得分:2)

问题是您正在尝试在每个数据库更新回调中发送JSON响应。对于请求,您只能发送一次响应。您可以使用Promise.all等待库存和产品更新,也可以使用Mongoose的bulkWrite功能。

bulkWrite效率更高,因为它只涉及对数据库的一个请求,而不涉及多个请求。

这是bulkWrite如何与您的代码一起工作的(未经实验的)示例:

router.put('/stockAccepted/:id', (req, res, next) => {   
  stockSchema.findOneAndUpdate({
    _id: req.params.id
  }, {
    $set: {
      stockAccepted: req.body.stockAccepted
    }
  }).then((result) => {
    let stockItem = req.body.stockItem;
    let updates = []
    stockItem.forEach((element) => {
      updates.push({
        updateOne: {
          filter: {
            _id: element.productId
          },
          update: {
            $inc: {
              productQuantity: element.productQuantity
            }
          }
        }
      })
    })
    return productSchema.bulkWrite(updates)
  }).then((result) => {
    res.json(result);
  }).catch((err) => {
    res.json(err);
  })
});

我使用的是从猫的数据库调用返回的promise,而不是回调,因为它减少了嵌套。

与您的版本不同,此代码将等待数据库中的库存更新。然后它将创建一个批量操作并将其发送到数据库。完成此操作后,它将最终以JSON的形式返回批量操作的响应。

请注意,最终捕获处理程序将捕获库存更新或批量产品更新中的错误。

答案 1 :(得分:0)

您正在使用forEach循环遍历stockItem,这没错。
您在这里可能会错过的是,在正确处理了第一个element参数之后,您直接使用了res参数,这就是为什么下一次迭代在处理相同的逻辑时会失败,并显示“已发送标题”,因为您实际上,已经用res发出了http响应。

我建议在循环过程中聚合您的result,并仅以您的聚合res作为json触发results,如下所示:

router.put('/stockAccepted/:id', (req, res, next) =>{    
    stockSchema.findOneAndUpdate({_id: req.params.id}, {
        $set:{
            stockAccepted: req.body.stockAccepted
        }
    },(err, result) => {
        if(err) res.json(err);
        else res.json(result);
    });

    let stockItem = req.body.stockItem;

    const results = [];
    const errors = [];

    stockItem.forEach((element) => {
        console.log("counter")
        productSchema.update({_id: element.productId}, { 
            $inc:{ 
                productQuantity: element.productQuantity
            } 
        }
        ,(err, result) => {
            if(err) errors.push(err);
            else result.push(result);
        });
    });

    res.json({
        results,
        errors
    });
});