试图删除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; }));