Mongoose删除嵌套对象数组元素save不生效及findByIdAndUpdate实现咨询
变更不生效原因
Mongoose对数组类型字段有独立的变更追踪逻辑,直接通过索引修改数组元素、使用delete运算符删除元素的操作都无法被识别,因此调用save()方法时不会将这部分变更同步到MongoDB。如果保留原有先查询再保存的写法,只需在修改完products数组后手动标记该字段变更即可:
order.products[e] = undefined; // 新增此行手动触发变更追踪 order.markModified('products');
findByIdAndUpdate实现方案
完全可以不操作内存中的文档对象,直接通过MongoDB更新运算符实现需求,两种常见场景的实现如下:
场景1:传入的ids是products数组的索引值
对应你原代码的逻辑,先通过$unset删除对应索引的元素,再用$pull清理数组中的空值:
const { ids } = req.body; try { let changedOrder; if (ids?.length) { // 构造unset参数 const unsetConfig = {}; ids.forEach(idx => { unsetConfig[`products.${idx}`] = ""; }); // 第一步删除对应索引元素 await Order.findByIdAndUpdate(req.params.id, { $set: { status: 'Partial' }, $unset: unsetConfig }); // 第二步清理数组空值,返回更新后的完整文档 changedOrder = await Order.findByIdAndUpdate( req.params.id, { $pull: { products: null } }, { new: true } ).populate('user', 'name').exec(); } else { // 无待删除元素时直接更新状态 changedOrder = await Order.findByIdAndUpdate( req.params.id, { status: 'Partial' }, { new: true } ).populate('user', 'name').exec(); } if (!changedOrder) { return res.status(404).json({ errors: [{ msg: 'Vous ne pouvez pas fermer une commande déjà fermée' }] }); } res.json(changedOrder); } catch (err) { console.log(err); res.status(500).json({ errors: [{ msg: 'Server Error' }] }); }
场景2:传入的ids是products数组中存储的产品ID
如果ids为待删除产品的_id而非数组索引,可直接用$pull一次性完成删除:
const { ids } = req.body; try { const changedOrder = await Order.findByIdAndUpdate( req.params.id, { $set: { status: 'Partial' }, $pull: { products: { _id: { $in: ids } } } }, { new: true } ).populate('user', 'name').exec(); if (!changedOrder) { return res.status(404).json({ errors: [{ msg: 'Vous ne pouvez pas fermer une commande déjà fermée' }] }); } res.json(changedOrder); } catch (err) { console.log(err); res.status(500).json({ errors: [{ msg: 'Server Error' }] }); }
内容的提问来源于stack exchange,提问作者lulu33
相关产品推荐
相关产品推荐

