0

I am building an application with node js and mongodb/mongoose,to make data manipulation easier, I used mongodb pollution,and without wanting to I ended up in a situation where I am not sure of the performance of the code.

For example, let's say I have 3 collections: -category -product -variation

when I display the product, the json structure is something like this.

{ 
  prodName:'test 1',
  qtyProd:3,
  ......
  category:[
    {
       _id:xcxxcxcxc,
       catName:'Test Cat',
       prodQty:10
    },
    {
       _id:abababababab,
       catName:'Test Cat 2',
       prodQty:12
    }
  ]
  .............
  variationProd:[
     {
       _id:dasdasdas,
        //variation data 
     },
     {
       _id:dasdasdas,
        //variation data 
     },
  ]
}

In situations where I delete a product, I have to do the following operations to delete all variations, and to adapt the quantity to all categories.

This is how my code looks like:Method:Patch

// Update Category Qty
exports.updateAllCat = async(req,res,next)=>{
    //Category / Product => name of collection
    const idProd = req.body.prodId;

    await Product.findById(idProd ,(err,resp)=>{
        if(err) ....
        
        resp.category.forEach(async(item)=>{
             //reduce prod qty from category
             let newQty = item.prodQty - resp.qtyProd;
             // update category qty
             await Category.findByIdAndUpdate(item._id,{
                 prodQty:newQty 
              },(e,cb)=>{
                   if(err) ....

                   next()
              })
         })
     })
}

// Delete Variation
exports.removeAllVariation = async(req,res,next)=>{
    //Variation/ Product => name of collection
    const idProd = req.body.prodId;

    await Product.findById(idProd ,(err,resp)=>{
        if(err) ....
        
        resp.variationProd.forEach(async(item)=>{
             //reduce prod qty from category
  
             // update category qty
             await Variation.findByIdAndDelete(item._id,(e,cb)=>{
                   if(err) ....

                   next()
              })
         })
     })
}

//return response to client side
exports.returnResponse = async(req,res)=>{
   res.status(200).json({
       status:"success"
       message:"Product deleted susccesfully"
   })
}

But I'm not sure if this method of using forEach is a good one,because it could give error if there are many variations or categories.

I thought of separating the functions, a function in which to bring all the ids and the new quantity and then send them to the next function using res.locals.categoryLocal <<[{id:1223, newCat:7}]>> and res.locals.variationIds <<[123,324]>>,but in the end I would still end up using forEach.

Is there another option, I don't know anything from mongoose deleteMany() or updateMany(), another approach, in general from what I found on the internet and on youtube I'm a bit confused.

1 Answers1

1
  1. dont use async with forEach , use modern loop instead like for..of. reff: https://stackoverflow.com/a/37576787/9267467
  2. deleteMany is used to delete in one colection,better to not use it

in the case, i would suggest to use transaction to perform multiple delete, multiple update and/or multiple insert for several collection in one of execution of a funtion to ensure all documents from several collection has been fetched/deleted/inserted

how to perform transaction with mongosee?

bese on you example, it would be like

// Using Mongoose's default connection
const session = await mongoose.startSession();

// Using custom connection
const db = await mongoose.createConnection(mongodbUri).asPromise();


// Delete Variation
exports.removeAllVariation = async (req, res, next) => {
    //always handle async function with try and catch
    try {
        import mongoose from 'mongoose'; // import mongoose
        
        const session = await mongoose.startSession(); //start transaction

        //Variation/ Product => name of collection
        const { prodId } = req.body.prodId;        
        const product = await Product.findById(idProd, {session});
    
        for (const item of product.variationProd) {
            // await Variation.findByIdAndDelete(item._id)
            // use deleteOne instead, no need to check if id exist or not
            await Variation.deleteOne(item._id, {session});
        }

        await session.endSession()
        next()
    } catch (error) {
        throw new Error('deletion failur') 
    }
};

Tobok Sitanggang
  • 607
  • 5
  • 15