Node.js开发购物车后端时如何避免新增重复商品而是增加已有商品数量?
问题修复步骤
1. 先修正数据模型的错误配置
你当前Schema中给userId设置了unique: true约束,这会导致同一个用户只能存在一条购物车记录,完全无法添加多个不同商品,首先移除该约束:
module.exports = (mongoose) => new mongoose.Schema( { // 移除unique: true,只保留必填约束 userId: { type: Number, required: true }, product: { productId: { type: Number, required: true }, slug: { type: String, required: true }, name: { type: String, required: true }, image: { type: String, required: true }, }, options: [ { optionId: { type: Number, required: true }, optionTitle: { type: String, required: true }, valueId: { type: Number, required: true }, valueTitle: { type: String, required: true }, }, ], price: { type: Number, required: true }, quantity: { type: Number, required: true, min: 1 }, }, { timestamps: true } );
2. 重写service层addItem方法
直接用MongoDB的findOneAndUpdate+upsert特性,一步实现「存在则更新数量、不存在则新建条目」的逻辑,无需手动判断是否存在:
注意:查询条件同时匹配
userId、product.productId和options,确保同个商品不同规格会被识别为不同购物车条目
const db = require('../models'); const logger = require('../utils/logger'); const service = 'cart'; const tag = service + '.js'; module.exports = { addItem: async (payload, auth) => { try { const userId = auth.credentials.customerId; // 查询条件:匹配用户、商品ID、商品规格 const query = { userId, 'product.productId': payload.product.productId, options: payload.options // 完全匹配商品规格,不同规格算不同条目 }; // 更新操作:存在则累加数量,不存在时插入的默认数据 const update = { $inc: { quantity: payload.quantity }, // 累加数量 $setOnInsert: { userId, product: payload.product, options: payload.options, price: payload.price } }; // 配置upsert=true,找不到匹配项时自动新建 const options = { upsert: true, new: true, runValidators: true }; const updatedCart = await db.Cart.findOneAndUpdate(query, update, options); return { success: true, data: updatedCart }; } catch (error) { logger.error(tag + ': add', error); return { success: false, data: error }; } }, };
逻辑说明
$inc操作符:匹配到已有条目时,自动对quantity字段做增量更新,不用手动读取再赋值$setOnInsert操作符:只有当触发新建操作(upsert)时才会写入这些字段,更新已存在条目时不会覆盖原有数据new: true配置:返回更新/新建后的最新数据runValidators: true配置:更新时也触发Schema的字段校验,避免非法数据写入
内容的提问来源于stack exchange,提问作者Tiger Mate
相关产品推荐
相关产品推荐

