Mongoose嵌套模式数组 – 对象没有方法“id”

我试图在Mongoose中定义一个文件夹模式。 对于每个文件夹,我想要存储一个对父文件夹的引用,以及一个子数据文件的数组(为了使两个方向的遍历都容易):

var folderSchema = new mongoose.Schema({ name: String, parent: { type: Schema.Types.ObjectId, ref: 'Folder' }, subfolders: [{ type: Schema.Types.ObjectId, ref: 'Folder' }], }); 

当创build一个文件夹,我希望能够只指定父文件夹,然后有一个预保存挂钩照顾添加到父文件夹的subfolders数组的subfolders 。 这部分工作正常:

 folderSchema.pre('save', function (next) { var self = this; // If creating a subfolder, then add the subfolder to // the parent folder's "subfolders" array if (this.parent) { Folder.findById(this.parent, function (err, parent) { if (err) return next(err); if (parent) { parent.subfolders.push(self); return parent.save(next); } return next(); }); } else { next(); } }); 

此外,删除子文件夹时,我想使用预先删除挂钩自动从父文件夹的subfolders数组中删除子文件subfolders 。 不幸的是,我无法让这部分工作:

 folderSchema.pre('remove', function (next) { var self = this; // If deleting a subfolder, then remove it from the parent // folder's "subfolders" array // // (Note: it would also be a good idea to recursively remove // all subfolders here, but I'm not attempting this yet.) if (this.parent) { Folder.findById(this.parent, function (err, parent) { if (err) return next(err); if (parent) { parent.subfolders.id(self._id).remove(); // TypeError: Object 53a64349741d1ae82274c9a2 has no method 'id' return parent.save(next); } return next(); }); } else { next(); } }); 

错误的是这一行:

 parent.subfolders.id(self._id).remove(); 

它导致这个错误:

 TypeError: Object 53a64349741d1ae82274c9a2 has no method 'id' at Promise.<anonymous> (C:\Users\serg\temp\mongoose\folders\index.js:53:35) at Promise.<anonymous> (C:\Users\serg\temp\mongoose\folders\node_modules\mongoose\node_modules\mpromise\lib\promise.js:177:8) at Promise.EventEmitter.emit (events.js:95:17) at Promise.emit (C:\Users\serg\temp\mongoose\folders\node_modules\mongoose\node_modules\mpromise\lib\promise.js:84:38) at Promise.fulfill (C:\Users\serg\temp\mongoose\folders\node_modules\mongoose\node_modules\mpromise\lib\promise.js:97:20) at C:\Users\serg\temp\mongoose\folders\node_modules\mongoose\lib\query.js:1393:13 at model.Document.init (C:\Users\serg\temp\mongoose\folders\node_modules\mongoose\lib\document.js:250:11) at completeOne (C:\Users\serg\temp\mongoose\folders\node_modules\mongoose\lib\query.js:1391:10) at Object.cb (C:\Users\serg\temp\mongoose\folders\node_modules\mongoose\lib\query.js:1150:11) at Object._onImmediate (C:\Users\serg\temp\mongoose\folders\node_modules\mongoose\node_modules\mquery\lib\utils.js:137:16) 

我正在尝试使用MongooseDocumentArray#id方法删除子文档,如Mongoose文档的Sub Docs页面上的示例所示。 但是,看起来这种方法是不可用的,我不知道这是为什么。 我是否错误地定义了模式? id方法在中间件中不可用吗? 或者我只是没有正确使用它?

这里的不同之处在于,您正在使用对数组中的对象的embedded式引用,而不是直接的子文档。 在子文件的mongoose示例中,它显示:

 var childSchema = new Schema({ name: 'string' }); var parentSchema = new Schema({ children: [childSchema] }); 

所以在这个例子中,每个“孩子”实际上直接存储在“父母”(所以孩子住在父母的collections)。 在您的scheme中,您有一个对您的subfolders ID的引用,而不是直接存储对象:

 subfolders: [{ type: Schema.Types.ObjectId, ref: 'Folder' }], 

所以当你执行查询时, subfolders的结果实际上是一个ID数组,其中一个是53a64349741d1ae82274c9a2 。 这没有任何方法,这是造成你的问题。 但是,您可以使用populate来填充这些ID的对象。 但即使这样做也不会给你所需要的DocumentArray函数,因为mongoose把它们当作一个Array而不是DocumentArray (它会有你正在寻找的id函数)。 你可以看到它用来确定如何在这里投射这些对象的逻辑 。 最后,你会看到,当你加载这些对象mongoose转换他们作为一个Arraytypes:

 return new Types.Array(path, cast || Types.Mixed, obj); 

所以,如果你想要这个id函数,你可以改变你的模式,或者干脆就这样做。 逻辑不是那么多 ,所以你可能会考虑只是手动search与ID匹配的数组。