我试图在Mongoose中定义文件夹架构。对于每个文件夹,我想存储对父文件夹的引用,以及子子文件夹的数组(以便在任一方向上进行遍历):
var folderSchema = new mongoose.Schema({
name: String,
parent: { type: Schema.Types.ObjectId, ref: 'Folder' },
subfolders: [{ type: Schema.Types.ObjectId, ref: 'Folder' }],
});
创建文件夹时,我希望只能指定父文件夹,然后让pre-save hook注意将子文件夹添加到父文件夹的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
数组中删除子文件夹。不幸的是,我无法让这部分工作:
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
方法?或者我只是没有正确使用它?
答案 0 :(得分:5)
这里的不同之处在于您使用的是对数组中对象的嵌入式引用,而不是直接子文档。在子文档的猫鼬示例中,它显示:
var childSchema = new Schema({ name: 'string' });
var parentSchema = new Schema({
children: [childSchema]
});
因此,在此示例中,每个“子”实际上直接存储在“父”中(因此子项存在于父集合中)。在您的方案中,您引用了subfolders
ID,而不是直接存储对象:
subfolders: [{ type: Schema.Types.ObjectId, ref: 'Folder' }],
因此,当您执行查询时,subfolders
中的结果实际上是一个ID数组,其中一个是53a64349741d1ae82274c9a2
。这没有导致问题的方法id
。但是,您可以使用populate
填充这些ID的对象。但即使这样做也不会为您提供所需的DocumentArray
功能,因为猫鼬只将Array
视为DocumentArray
,而不是id
(会有Array
你正在寻找的功能)。 You can see the logic which it uses to determine how to cast these objects here。最后,你会看到当你加载这些对象时,mongoose将它们转换为return new Types.Array(path, cast || Types.Mixed, obj);
类型:
id
因此,如果您需要此{{1}}功能,则可以更改架构,或者只是执行它所做的工作。 The logic isn't that much,因此您可以考虑仅在数组中搜索与该ID匹配的那个。