Search code examples
mongodbmongoosemongoose-schemamongoose-populate

Mongoose autopupulates user carts with product items


i am trying to perform add to cart to user's cart, following is the schema for user - cart associated with user

export interface CartType extends Document {
  productId: string;
  quantity: number;
}

export interface UserModelType extends Document {
  _id: string;
  firstname: string;
  lastname: string;
  username: string;
  email: string;
  password: string;
  cart: [CartType];
  readEmail: (product: string) => void;
}

const userSchema = new Schema(
  {
    firstname: {
      type: String,
      required: true,
      lowercase: true,
    },
    lastname: {
      type: String,
      required: true,
      lowercase: true,
    },
    username: {
      type: String,
      required: true,
      lowercase: true,
      unique: true,
    },
    email: {
      type: String,
      required: true,
      lowercase: true,
      unique: true,
    },
    password: {
      type: String,
      required: true,
    },
    cart: [
      {
        productId: {
          type: Schema.Types.ObjectId,
          required: true,
          ref: 'Product',
        },
        quantity: {
          type: Number,
          required: true,
        },
      },
    ],
    createdAt: {
      type: Date,
      required: true,
    },
    updatedAt: {
      type: Date,
      default: Date.now(),
    },
  },
  { versionKey: false }
);

I am also using populate for cart as follows:

return UserModel.findOne({ _id })
  .populate({
    path: 'cart',
    populate: {
      path: 'productId',
      model: 'Product',
    },
  });

Following is the code logic for adding to cart


//CODE LOGIN FOR ADDING TO CART
const userCart = req.user.cart;
    const cartItem = {
      productId: product._id.toString(),
      quantity: 1,
    } as CartType;

    const ind = _.findIndex(userCart, (thisCart) => {
      // thisCart should have productId and quatity, but here I am getting thisCart.productId.Product already populated, I am using populate only in getUsers route[![enter image description here][1]][1]
      console.log(`cart Item: ${thisCart}`);
    });

    userCart.push(cartItem);
    await UserModel.updateOne(
      {
        _id: req.user._id,
      },
      {
        $set: {
          cart: userCart,
        },
      }
    );

I am expecting cart should have "productId", "quantity", But when I look for user.cartm I am getting user.cart.productId.Product

This was working fine earlier when populate was not implemented...

IN mongodb following fields getting saved in cart: productId, quantity, but when I iterate on user.cart, I am getting entire Product object, I do not expect it get populate while internal mongoose methods.

Kindly help!


Solution

  • I was able to resolve the issue, I think we have to depopulate the user object before we iterate on it...

    userSchema.method('addToCart', function (productId: string) {
      this.depopulate(); // this will remove the effect of populated cart
      const prodIndex = _.findIndex(this.cart, (thisCart: CartType) => {
        // console.log(
        //   `this card id: ${thisCart.productId.toString} received: ${productId}`
        // );
        return thisCart.productId.toString() === productId;
      });
    
      if (prodIndex >= 0) {
        this.cart[prodIndex].quantity += 1;
      } else {
        const newCartItem = {
          productId,
          quantity: 1,
        } as CartType;
        this.cart.push(newCartItem);
      }
      this.save();
    });