Delete array element in document and save but it remains anyway (MongoDb using NodeJS)

Viewed 103

I have a shopping cart. In the current state of the schema, each element contained in it is represented by an object in the Products array. Each call to the function removes a quantity equal to 1 of the object passed through its itemId. When I want to remove an object with quantity equal to 1 (so the quantity value reaches 0) I want to remove the object from the cart (so itemId & quantity) from the Products array. The case that if it is greater than 1, when there is only to decrease the value of quantity it works, instead when there is to eliminate the product no, the message 'Deleted item in cart. but it is not true, it remains in the database anyway

Cart Schema

const mongoose = require('mongoose');
const idValidator = require('mongoose-id-validator');

const Schema = mongoose.Schema;
 

const cartSchema = new Schema ({
    products: [
        {
            productId: { type: mongoose.Types.ObjectId, required: true, ref: 'Product' },
            quantity: { type: Number, required: true },
        }
    ],
    customer: { type: mongoose.Types.ObjectId, required: true, unique: true, ref: 'User'}
});


cartSchema.plugin(idValidator);
module.exports = mongoose.model('Cart', cartSchema);

Function to decrease

const removeToCartByUserId = async (req, res, next) => {
    const userId = req.params.uid; 
    const { productId } = req.body;
    const quantity = 1;
    try {
        let cart = await Cart.findOne({customer: userId});

        //Cart exist for user
        if(cart) {
            let itemIndex = cart.products.findIndex(p => p.productId == productId);

            //product exists in the cart, update the quantity
            if (itemIndex > -1) {
                let productItem = cart.products[itemIndex];
                if(productItem.quantity > 1) {
                    productItem.quantity -= quantity;
                    cart = await cart.save();
                    res.status(201).json({ cart });
                } else { // delete product in array
                    await cart.products.pull({ productId: productId }) // removed
                    cart = await cart.save();
                    res.status(200).json({ message: 'Deleted item in cart.' });
                }
            } 
        } else { // no Cart for the user, exit
            const error = new HttpError('Something went wrong with the cart.', 500);
            return next(error); 
        }
    } catch(err) {
        console.log(err);
        const error = new HttpError('Something went wrong with the cart.', 500);
        return next(error); 
    }
};

Update: I edited the code and now it works

 //product exists in the cart, update the quantity
if (itemIndex > -1) {
    let productItem = cart.products[itemIndex];
    productItem.quantity -= quantity;
    if(productItem.quantity > 0) {
        cart = await cart.save();
        res.status(201).json({ cart });
    } else { // delete product in array
        await Cart.updateOne(
            { itemIndex },
            {$pull : { "products": { productId } } }
            );

        res.status(200).json({ message: 'Deleted item in cart.' });
    }
}
1 Answers

Change your code a bit.

        //product exists in the cart, update the quantity
        if (itemIndex > -1) {
            let productItem = cart.products[itemIndex];
            productItem.quantity -= quantity;
            if(productItem.quantity > 1) {
                cart = await cart.save();
                res.status(201).json({ cart });
            } else { // delete product in array
                await cart.products.pull({ productId }) // removed

                res.status(200).json({ message: 'Deleted item in cart.' });
            }
        }

You need to decrease the product quality before the if otherwise the else statement won't be called, when it should be.

Also, I have removed cart.save call, it maybe so that your local data is outdated after call to pull so calling a save would update the database with data that you had before pull and thus revert deleting of an item.

Related