node.js - Mongoose 嵌套架构数组 - 对象没有方法 'id'

标签 node.js mongoose

我正在尝试在 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();
    }
});

此外,在删除子文件夹时,我想使用预删除 Hook 自动从父文件夹的 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方法删除子文档,如 Sub Docs 上的示例所示Mongoose 文档的页面。但是,该方法似乎不可用,我不确定为什么会这样。我是否错误地定义了架构? id 方法在中间件中不可用吗?或者我只是没有正确使用它?

最佳答案

这里的区别在于您使用的是对数组中对象的嵌入引用,而不是直接的子文档。在子文档的 mongoose 示例中,它显示:

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

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

因此,在这个示例中,每个“子项”实际上直接存储在“父项”中(因此子项位于父集合中)。在您的场景中,您可以引用您的子文件夹 ID,而不是直接存储对象:

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

因此,当您执行查询时,subfolders 中的结果实际上是一个 ID 数组,其中之一是 53a64349741d1ae82274c9a2。这没有导致您的问题的方法id。但是,您可以使用 populate填充这些 ID 的对象。但即使这样做也不会为您提供所需的 DocumentArray 函数,因为 mongoose 将它们视为简单的 Array,而不是 DocumentArray (其中将具有您正在寻找的 id 函数)。 You can see the logic which it uses to determine how to cast these objects here 。最后,您将看到,当您加载这些对象时, Mongoose 将它们转换为 Array 类型:

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

因此,如果您想要这个 id 函数,您可以更改您的架构,或者简单地执行它的操作。 The logic isn't that much ,因此您可能会考虑手动在数组中搜索与该 ID 匹配的数组。

关于node.js - Mongoose 嵌套架构数组 - 对象没有方法 'id',我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24352681/

相关文章:

node.js - mongoose模型如何与mongodb连接?

javascript - 使用带 typescript 的 Mongoose 创建自定义验证时出错

node.js - MongoDB - 如何使用 Node.js 获取集合的大小?

node.js - 无法让 `cookieSession` 与 `maxAge` 一起使用

node.js - 如何在 Typescript 中重新导入模块

node.js - Mongoose 使用父字段生成子字段

mongodb - Mongoose 中的 findByIdAndUpdate() 和 findOneAndUpdate() 有什么区别?

javascript - 无法从子进程获取管道流

node.js - Swagger-UI-Express 未在 Azure 应用服务中加载 : 404 Not Found

javascript - Mongoose 使用方法将模式添加到模式中