猫鼬嵌套模式数组-对象没有方法'id'

Ser*_*y K 1 mongoose node.js

我正在尝试在Mongoose中定义一个文件夹架构。对于每个文件夹,我想存储对父文件夹以及子子文件夹数组的引用(以使在任一方向的遍历都变得容易):

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

创建文件夹时,我只希望指定父文件夹,然后使用预先保存的钩子将子文件夹添加到父文件夹的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();
    }
});
Run Code Online (Sandbox Code Playgroud)

另外,在删除子文件夹时,我想使用预删除钩子自动从父文件夹的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();
    }
});
Run Code Online (Sandbox Code Playgroud)

错误的这一行是这一行:

parent.subfolders.id(self._id).remove();
Run Code Online (Sandbox Code Playgroud)

它导致此错误:

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)
Run Code Online (Sandbox Code Playgroud)

我试图做的是使用该MongooseDocumentArray#id方法删除子文档,如Mongoose文档的“ 子文档”页面上的示例所示。但是,该方法似乎不可用,我不确定为什么会这样。我定义的模式不正确吗?该id方法在中间件中不可用吗?还是我只是使用不正确?

dyl*_*nts 5

此处的区别在于您使用的是对数组中对象的嵌入式引用,而不是直接的子文档。在子文档的猫鼬示例中,它显示:

var childSchema = new Schema({ name: 'string' });

var parentSchema = new Schema({
  children: [childSchema]
});
Run Code Online (Sandbox Code Playgroud)

因此,在此示例中,每个“子”实际上直接存储在“父”中(因此子生活在父集合中)。在您的方案中,您引用的是subfoldersID,而不是对象的直接存储:

subfolders: [{ type: Schema.Types.ObjectId, ref: 'Folder' }],
Run Code Online (Sandbox Code Playgroud)

因此,当您执行查询时,结果subfolders实际上是ID数组,其中一个是53a64349741d1ae82274c9a2。这没有id导致您的问题的方法。但是,您可以使用populate这些ID填充对象。但是即使那样做也不能满足您的DocumentArray需要,因为猫鼬将其简单地视为Array,而不是DocumentArray(将具有id您要查找的功能)。 您可以在此处看到用于确定如何投射这些对象的逻辑。最后,您会看到当加载这些对象时,猫鼬会将它们转换为一种Array类型:

return new Types.Array(path, cast || Types.Mixed, obj);
Run Code Online (Sandbox Code Playgroud)

因此,如果您想使用此id功能,则可以更改架构,也可以直接执行其功能。 逻辑不是那么多,因此您可以考虑只在阵列中搜索手动匹配该ID的那个。