Mongoose从可能为空的数组按属性值移除对象报错求助
解决Mongoose $pull操作空数组时的MongoError问题
我刚碰到过类似的问题,这个错误的根源是你使用$pull的方式不对——当pending_approval是空数组时,MongoDB没办法从空数组里遍历到service_order字段,所以抛出了这个错误码为28的MongoError。
问题分析
你原来的$pull写法直接指定了嵌套字段路径service_orders.pending_approval.service_order,但当pending_approval是空数组时,MongoDB尝试访问数组元素的子字段,这显然是不可能的,因此触发了遍历错误。
解决方案
调整$pull的语法,直接针对pending_approval数组中的对象进行匹配,同时注意几个关键细节:
var marked_vendors = ["5a76c4566b0e8c261cc47496", "5b05380f1cab52045c2afc1a"]; // ObjectId字符串需加引号 Vendor.update( { '_id': { $in: marked_vendors } }, { $pull: { 'service_orders.pending_approval': { service_order: mongoose.Types.ObjectId(req.body.serviceorder_id) // 转换为ObjectId类型 } } }, { new: true, multi: true } // multi: true确保更新所有匹配的文档 ).exec(function(err, vendors) { if (err) { console.log(err); return res.json({ success: false, msg: err }); } else { return res.json({ success: true, msg: 'Successfully pulled' }); } });
关键说明
- 正确的$pull语法:
$pull需要作用于数组字段(这里是service_orders.pending_approval),传入的是匹配数组元素的条件对象,而不是子字段路径。这样MongoDB会自动处理空数组的情况——空数组时不会执行任何操作,自然不会报错。 - ObjectId转换:你的Schema中
service_order是ObjectId类型,所以要把req.body.serviceorder_id转换成mongoose.Types.ObjectId,否则字符串可能无法匹配到对应的ObjectId值。 - multi选项:因为你用了
$in查询多个Vendor文档,默认update方法只更新第一个匹配的文档,添加multi: true才能更新所有符合条件的文档。 - 错误捕获:你之前的
try/catch无效是因为错误是在异步的exec回调中抛出的,同步的try/catch无法捕获异步错误,必须在回调函数中处理错误,就像你当前的代码结构一样。
内容的提问来源于stack exchange,提问作者Achira Shamal
相关产品推荐
相关产品推荐

