Я хочу увеличить количество документов в mongodb - PullRequest
0 голосов
/ 26 сентября 2018
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 голосов
/ 26 сентября 2018

Проблема в том, что вы пытаетесь отправить ответ 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);
  })
});

Я использую обещание, возвращенное из БДзвоните в mongoose, а не в обратные вызовы, так как это уменьшает вложенность.

В отличие от вашей версии, этот код будет ожидать обновления запасов в БД.Затем он создаст массовую операцию и отправит ее в БД.Как только это будет выполнено, он, наконец, вернет ответ от массовой операции в виде JSON.

Обратите внимание, что обработчик окончательного улова будет обнаруживать ошибки как при обновлении, так и при массовом обновлении продукта.

0 голосов
/ 26 сентября 2018

Вы перебираете цикл stockItem с циклом forEach, в этом нет ничего плохого.
Здесь вам, вероятно, не хватает того, что после правильной обработки первых element вы напрямую используете параметры res, поэтомуСледующая итерация, когда вы обрабатываете ту же логику, она завершается с ошибкой «заголовки уже отправлены», потому что вы действительно уже запускаете HTTP-ответ с res.

. Я предлагаю объединить ваши result во время цикла.и стреляйте по res с вашим совокупным значением results как json, как показано ниже:

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
    });
});
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...