试图删除Mongoose中的一个子文档给我一个内部mongoose错误
我有一个架构如下(简体):
var Permission = new Schema({ _id: String, // email address role: String // "admin" or "member" }); var Org = new Schema({ name: {type: String, index: {unique: true, dropDups: true}, trim: true}, permissions: [Permission] });
示例文档将如下所示:
{ "name": "My Org", "permissions" : [ {"_id" : "joe@gmail.com", "role" : "admin"}, {"_id" : "mary@gmail.com", "role" : "member"} ] }
我试图删除其中一个权限行,使用命令org.permissions.remove(req.params.email)
,如下文所示:
exports.removePermissions = function(req, res) { var name = req.params.name; return Org .findOne({name: name}) .select() .exec(function(err, org) { if (err) return Org.handleError(res, err); if (!org) return Org.handleError(res, new Error("#notfound " + name)); org.permissions.remove(req.params.email); org.save(function(err, org) { if (err) return Org.handleError(res, err); else return res.send(org); }); }); };
当我这样做,我得到以下错误:
TypeError: Cannot use 'in' operator to search for '_id' in joe@gmail.com at EmbeddedDocument.Document._buildDoc (/../node_modules/mongoose/lib/document.js:162:27) at EmbeddedDocument.Document (/../node_modules/mongoose/lib/document.js:67:20) at EmbeddedDocument (/../node_modules/mongoose/lib/types/embedded.js:27:12) at new EmbeddedDocument (/../node_modules/mongoose/lib/schema/documentarray.js:26:17) at MongooseDocumentArray._cast (/../node_modules/mongoose/lib/types/documentarray.js:62:10) at Object.map (native) at MongooseDocumentArray.MongooseArray.remove (/../node_modules/mongoose/lib/types/array.js:360:21) at model.Org.methods.removePermissions (/../models/org.js:159:20)
我唯一能想到的是,Mongoose不支持不是ObjectID的_id字段? 这很奇怪,因为我在我的代码中使用了其他地方,它工作正常(例如org.permissions.id(“joe@gmail.com”)工作)。
任何build议非常感谢!
我不知道为什么使用remove
没有工作,但你可以使用findOneAndUpdate
和$pull
操作符自动执行此操作:
exports.removePermissions = function(req, res) { var name = req.params.name; return Org.findOneAndUpdate( {name: name}, {$pull: {permissions: {_id: req.params.email}}}, function(err, org) { // org contains the updated doc ... }); };
根据这个答案 ,你需要调用你想要删除的子文档的remove()
,而不是整个子文档数组。
所以,改变:
org.permissions.remove(req.params.email);
至:
org.permissions.id(req.params.email).remove();
这两步方法比@JohnnyHK提供的答案更有优势,因为您可以在删除子文档之前validation子文档是否真实存在。 如果您想要发送一个404响应来指示子文档不存在,那么这可能很有用 – 据我所知,使用$ pullprimefaces操作符是不可能的。
请注意,这也只会工作,如果你的子文档数组有一个模式,如问题所示。 如果不是,或者它的模式types是Mixed
,则从数据库返回的集合将是一个普通数组而不是Mongoose增强数组。 这意味着没有.id()
函数。 在这种情况下,我会使用lodash#remove来代替:
_.remove(org.permissions, (function(permission) { return permission._id.toString() === req.params.email; }));