You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Mongoose购物车添加商品时相同productId判断失效问题

购物车添加商品逻辑修复问题

问题背景

用户定义的Mongoose User Schema如下:

const userSchema = new mongoose.Schema(
  {
    name: { type: String, required: true },
    email: { type: String, unique: true },
    password: { type: String, required: true },
    image: { type: String, required: true, default: 'placeholder.jpg' },
    isAdmin: { type: Boolean, default: false },
    cart: [
      {
        product: { type: mongoose.Schema.Types.ObjectId, ref: 'Product' },
        quantity: { type: Number, required: true },
      },
    ],
  },
  { timestamps: true }
);

期望实现:添加商品到购物车时,若已存在相同productId的商品则增加数量,否则新增条目。但当前实现的addToCart函数每次都会重复添加条目,未正确累加数量:

export const addToCart = expressAsyncHandler(async (req, res) => {
  const { productId, quantity } = req.body;

  const user = await User.findById(req.user._id).select('cart');
  if (user) {
    const productInCart = user.cart.find((item) => item.product === productId);
    if (productInCart) {
      productInCart.quantity += quantity;
    } else {
      user.cart.push({ productId, quantity });
    }
    await user.save();
    res.json(user);
  } else {
    res.status(401);
    throw new Error('User does not exist');
  }
});

问题原因

  1. 类型不匹配:item.product是Mongoose的ObjectId对象,而productId是字符串类型,直接用===比较永远不相等,导致每次都判定为“商品未在购物车中”,执行新增逻辑。
  2. 字段名不匹配:push新条目时用了productId作为键名,但Schema中定义的字段是product,虽然Mongoose会自动映射,但规范写法应该保持一致。

修复后的代码

export const addToCart = expressAsyncHandler(async (req, res) => {
  const { productId, quantity } = req.body;

  const user = await User.findById(req.user._id).select('cart');
  if (user) {
    // 方法1:将ObjectId转为字符串后比较
    const productInCart = user.cart.find((item) => item.product.toString() === productId);
    
    // 方法2:使用ObjectId的equals方法(更推荐)
    // const productInCart = user.cart.find((item) => item.product.equals(productId));

    if (productInCart) {
      productInCart.quantity += quantity;
    } else {
      // 修正字段名,与Schema保持一致
      user.cart.push({ product: productId, quantity });
    }
    await user.save();
    res.json(user);
  } else {
    res.status(401);
    throw new Error('User does not exist');
  }
});

额外优化建议

可以改用Mongoose的原子更新操作(如findOneAndUpdate),避免先查询再保存的两步操作,提升性能并减少并发问题:

export const addToCart = expressAsyncHandler(async (req, res) => {
  const { productId, quantity } = req.body;

  // 先尝试更新已有商品的数量
  const updatedUser = await User.findOneAndUpdate(
    { _id: req.user._id, "cart.product": productId },
    { $inc: { "cart.$.quantity": quantity } },
    { new: true }
  );

  if (updatedUser) {
    return res.json(updatedUser);
  }

  // 如果没有找到对应商品,添加新条目
  const user = await User.findOneAndUpdate(
    { _id: req.user._id },
    { $push: { cart: { product: productId, quantity } } },
    { new: true }
  );

  if (user) {
    res.json(user);
  } else {
    res.status(401);
    throw new Error('User does not exist');
  }
});

内容的提问来源于stack exchange,提问作者dyaipayan

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.14 14:27:52