node.jsexpressmongoose

Mongoose Model.save() not working inside a loop


I'm working on an Express controller to update product's inventories when saving an order. Below is the code to recalculate sold & sellable amount of a product.

for (const lineItem of order.lineItems) {
    const product = await Product.findById(lineItem.productId);
    const inventories = [];
    for (const inventory of product.inventories) {
        inventory.sold = inventory.sold + lineItem.quantity;
        inventory.sellable = inventory.sellable - lineItem.quantity;
        inventories.push(inventory);
    }
    try {
        product.inventories = inventories;
        await product.save() // This, somehow, doesn't work.
    } catch (error) {
        loggerService.info(error)
    }
}

Somehow, the product.save() doesn't work. I did try to test the save outside the for-of loops, and it worked well.

Am I missing something?


Solution

  • This is because you're mutating subdocuments inside an array, and Mongoose doesn't detect the change.

    Use markModified in this (code is optimized.)

    for (const lineItem of order.lineItems) {
      const product = await Product.findById(lineItem.productId);
    
      for (const inv of product.inventories) {
        inv.sold += lineItem.quantity;
        inv.sellable -= lineItem.quantity;
      }
    
      product.markModified('inventories'); // force mongoose to treat as changed
      await product.save();
    }