0

I am trying to add a product to a shopping cart in mongodb but the code I have written does not work. It was previously working but when I switched from local mongodb to mongodb atlas cloud and then back to local mongodb it started having issues because it will not use the cart that gets created when redirected to '/' root and instead will keep creating a new cart with a new req.session.cartId belonging to it each time a product is added to cart. I have had so many issues with this one section and it is the final part of my project to get working before live hosting. Any help is appreciated. thank you.

const express = require('express');
const Carts = require('../repo/carts');
const Product = require('../repo/products');
const cartShowTemplate = require('../views/carts/show');

const router = express.Router();
let cart;

router.post('/cart/products', async (req, res) => {
  try {
    cart = await Carts.findById(req.session.cartId);
    // Check if cart exists
    if (!cart) {
      // Create new cart
      cart = await Carts.create({
        _id: req.session.cartId,
        items: [],
      });
    }

    // Check if product is present
    const productIndex = cart.items.findIndex(
      (item) => item._id === req.body.productId
    );
    if (productIndex === -1) {
      // Create new product
      cart.items.push({
        _id: req.body.productId,
        quantity: 1,
      });
    } else {
      // Update existing product
      cart.items[productIndex].quantity += 1;
    }

    // Save updated cart
    await cart.save();
    console.log(cart);
    res.status(200).send('product added to cart!!');
  } catch (err) {
    res.status(500).send('there was an error');
  }
});
        module.exports = router;

example of the array
the correct product gets added but a new cart with a new id gets created each time instead of using the same cart. I am not sure if this helps but what I noticed when I console.log(req.sessionID) it will show the same ID each time its console.logged but when console.logging (req.session.cartId) that will show as undefined when before it was showing an id.

enter image description here

carts schema

const mongoose = require('mongoose');

const cartSchema = new mongoose.Schema({
  _id: String,
  items: [
    { quantity: Number, _id: String }
  ]
});

const Carts = new mongoose.model('Carts', cartSchema);

module.exports = Carts;
rachel
  • 59
  • 7

2 Answers2

1

I'm not really sure about this but it looks like you might have an issue with async methods.

This method does not have neither an await nor a callback function, so the proccess will continue (and maybe finish) without waiting for it to finish.

    Carts.updateOne(
       {_id: req.body.productId },
       { $inc: {  quantity: 1 } }
    );

https://mongoosejs.com/docs/api.html#query_Query-updateOne (If you look at the example there, it's being awaited)

On the other hand, you should get this block:

  Carts.updateOne(
    { _id: foundCart._id },
    {
      $push: {
        items: {
          _id: req.body.productId,
          quantity: 1,
        },
      },
    },
    (err, updatedCart) => {
      if (err) {
        console.log(err);
      }
    }
  );

Inside of an else block. So if you find an existing item with the id you try to update it, but only if you don't find it you'll push a new item into the cart.

It should look something like this:

  if (check.includes(req.body.productId)) {
    console.log('MATCH FOUND');
    Carts.updateOne(
       {_id: req.body.productId },
       { $inc: {  quantity: 1 } }
    );
  } else {
    Carts.updateOne(
      { _id: foundCart._id },
      {
        $push: {
          items: {
            _id: req.body.productId,
            quantity: 1,
          },
        },
      },
      (err, updatedCart) => {
        if (err) {
          console.log(err);
        }
      }
    );
 }
Sunderam Dubey
  • 1
  • 11
  • 20
  • 40
  • thank you. this helps stop the user from adding the same product to the DB and creating multiple entries but unfortunately I am still having issues updating the quantity of the selected item. – rachel Nov 01 '22 at 01:45
  • Can you try this: https://stackoverflow.com/questions/15691224/mongoose-update-values-in-array-of-objects ? Instead of using _id to search, you should be able to use "items._id" – Facundo Gallardo Nov 01 '22 at 02:33
1

Try with this logic:

router.post('/cart/products', async (req, res) => {
  try {
    let cart = await Carts.findById(req.session.cartId);
    // Check if cart exists
    if (!cart) {
      // Create new cart
      cart = await Carts.create({
        _id: req.session.cartId,
        items: [],
      });
    }

    // Check if product is present
    const productIndex = cart.items.findIndex(
      (item) => item._id === req.body.productId
    );
    if (productIndex === -1) {
      // Create new product
      cart.items.push({
        _id: req.body.productId,
        quantity: 1,
      });
    } else {
      // Update existing product
      cart.items[productIndex].quantity += 1;
    }

    // Save updated cart
    await cart.save();

    res.status(200).send('product added to cart!!');
  } catch (err) {
    res.status(500).send('there was an error');
  }
});
lpizzinidev
  • 12,741
  • 2
  • 10
  • 29
  • this was working but now its throwing an error. MongooseError: document must have an _id before saving at /node_modules/mongoose/lib/model.js:299:18. Do you have any idea why this could be? I've looked up that defining the _id in the carts schema could be the issue but that does not explain why it was working before. – rachel Nov 01 '22 at 22:47
  • 1
    @rachel This might be a problem related t the push of a new item. Try to set only the quantity (the `_id` should be auto-generated): `cart.items.push({ quantity: 1 });` – lpizzinidev Nov 02 '22 at 07:40
  • Thank you for responding. What I've found is that it is the cartId causing the issue. Instead i deleted the req.session.cartId from Carts.create and now it will create a cart but it will keep creating new carts inside the DB each time an item is added instead of saving and using the saved cart. I have added the cart schema I am using to the code above, – rachel Nov 02 '22 at 10:47
  • 1
    @rachel You should not overwrite the `_id` attribute in your schema declaration. It is the default identifier for MongoDB. If you need to declare a custom identifier for your collection you should declare a field with a different name and add a unique constraint to it. – lpizzinidev Nov 02 '22 at 13:43