Mongoose用户购物车自动填充Product对象问题求助
问题:添加商品到购物车时,cart项被自动填充为完整Product对象
我正在实现添加商品到用户购物车的功能,用户Schema定义如下:
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 } );
我仅在获取用户信息的路由中使用了populate操作:
return UserModel.findOne({ _id }) .populate({ path: 'cart', populate: { path: 'productId', model: 'Product', }, });
但在添加商品到购物车的逻辑中,遍历req.user.cart时,每个cart项的productId被自动填充为完整的Product对象,而非仅存储的ObjectId:
//CODE LOGIC 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只有productId和quantity,但实际拿到了完整的Product对象 console.log(`cart Item: ${thisCart}`); }); userCart.push(cartItem); await UserModel.updateOne( { _id: req.user._id, }, { $set: { cart: userCart, }, } );
数据库中存储的cart字段确实只有productId和quantity,未使用populate前功能正常,现在需要阻止Mongoose自动填充cart中的Product对象。
解决方案
1. 重新获取未populate的用户对象
req.user是经过populate后的Mongoose文档实例,其cart项已被填充Product数据。直接操作该对象保存会带入填充后的内容,正确做法是从数据库重新拉取未填充的用户数据:
// 重新获取未执行populate的用户 const user = await UserModel.findById(req.user._id); if (!user) { /* 处理用户不存在的情况 */ } const userCart = user.cart; const cartItem = { productId: product._id, quantity: 1, } as CartType; // 检查商品是否已在购物车 const ind = _.findIndex(userCart, item => item.productId.toString() === product._id.toString()); if (ind === -1) { userCart.push(cartItem); } else { // 商品已存在则增加数量 userCart[ind].quantity += 1; } await user.save();
2. 将Mongoose文档转为纯JSON对象
如果要基于req.user操作,可将其转换为纯JavaScript对象,剥离Mongoose的自动填充逻辑:
// 转换为纯JS对象,移除Mongoose文档的自动填充特性 const userData = req.user.toObject(); const userCart = userData.cart; const ind = _.findIndex(userCart, item => item.productId.toString() === product._id.toString()); const updatedCart = [...userCart]; if (ind === -1) { updatedCart.push({ productId: product._id, quantity: 1 }); } else { updatedCart[ind].quantity += 1; } await UserModel.updateOne( { _id: req.user._id }, { $set: { cart: updatedCart } } );
3. 使用MongoDB原子更新操作(推荐)
直接通过数据库原子操作修改购物车,完全绕过Mongoose文档实例的自动填充问题,同时性能更优:
// 商品不存在则添加到购物车 await UserModel.updateOne( { _id: req.user._id, "cart.productId": { $ne: product._id } }, { $push: { cart: { productId: product._id, quantity: 1 } } } ); // 商品已存在则增加数量 await UserModel.updateOne( { _id: req.user._id, "cart.productId": product._id }, { $inc: { "cart.$.quantity": 1 } } );
内容的提问来源于stack exchange,提问作者Ghanshyam Baviskar
相关产品推荐
相关产品推荐

