Mongoose更新嵌套对象数组前校验值存在性,实现购物车商品增改逻辑
问题原因
你当前代码的核心问题是只覆盖了「目标商品未加入购物车」的单一场景,没有处理商品已存在时的增量更新逻辑:
- 过滤条件携带了
"cart.product": { $nin: [req.body.id] }规则,当商品已经在购物车中时,查询无法匹配到对应文档,不会执行任何更新 - 没有对查询到的商品信息做非空校验,传入无效商品ID时会直接触发后续计算报错
- 缺少总金额
totalPrice字段的同步更新逻辑,会导致明细和总金额数据不一致
修复后代码
router.put("/add-to-cart", authenticateToken, async (req, res) => { try { // 先校验商品是否存在 const productInfo = await productSchema.findById(req.body.id); if (!productInfo) { return res.status(400).send({ status: false, message: "商品不存在" }); } const addAmount = Number(req.body.amount) || 0; if (addAmount <= 0) { return res.status(400).send({ status: false, message: "添加数量必须大于0" }); } const addPrice = addAmount * productInfo.productPrice; // 一次原子查询同时处理两种场景 const updateResult = await cartSchema.findOneAndUpdate( // 只过滤用户,不限制购物车是否有该商品 { user: req.user }, [ { $set: { // 先处理已存在商品的增量更新 cart: { $map: { input: "$cart", in: { $cond: [ { $eq: ["$$this.product", req.body.id] }, { $mergeObjects: [ "$$this", { amount: { $add: ["$$this.amount", addAmount] }, price: { $add: ["$$this.price", addPrice] } } ] }, "$$this" ] } } }, totalPrice: { $add: ["$totalPrice", addPrice] } } }, { // 商品不存在时插入新条目 $set: { cart: { $cond: [ { $in: [req.body.id, "$cart.product"] }, "$cart", { $concatArrays: [ "$cart", [{ product: req.body.id, amount: addAmount, price: addPrice }] ] } ] } } } ], // 对应用户购物车不存在时自动创建 { upsert: true, new: true, setDefaultsOnInsert: true } ); return res.status(200).send({ status: true, data: updateResult }); } catch (err) { res.status(500).send({ status: false, message: err.message }); } });
逻辑说明
- 提前做商品有效性、添加数量的合法性校验,提前拦截非法请求
- 用聚合更新的
$map算子遍历购物车数组,匹配到对应商品时自动累加数量和金额,同步更新总金额 - 用
$cond判断商品是否已存在,不存在时才通过$concatArrays插入新的商品条目 - 全程是单原子更新操作,不需要多次查询数据库,不存在并发更新的数据一致性问题
内容的提问来源于stack exchange,提问作者Sang
相关产品推荐
相关产品推荐

