【问题标题】:Making a mongoose model aware that it is nested让猫鼬模型意识到它是嵌套的
【发布时间】:2014-05-17 00:41:19
【问题描述】:

考虑适合嵌套的博客/评论模式(即使您不同意):

var CommentSchema = new Schema({ name: String, body: String });
var BlogPostSchema = new Schema({ title: String, comments: [CommentSchema] });

我了解如何为博客文章添加、更新、删除 cmets,但所有这些方法都需要在父博客文章文档上调用 save() 方法:

blog_post.comments.push( new Comment({...}) );
blog_post.save();

我希望能够让 Comment 架构知道它嵌套在另一个架构中,这样我就可以在评论文档上调用 save() 并且它足够智能以更新父博客文章。在我的应用逻辑中,我已经知道博文 id,所以我想做这样的事情:

CommentSchema.virtual('blog_post_id');
CommentSchema.pre('save', function (next) {
    var comment = this;
    if( !comment.blog_post_id ) throw new Error('Need a blog post id');
    BlogModel.findById( comment.blog_post_id, function(err, post) {
        post.comments.push( comment );
        post.save(next);
    });
});

var comment = new Comment({ blog_post_id: 123, name: 'Joe', body: 'foo' });
comment.save();

上述方法可行,但我仍然会得到一个独立于博客文章的顶级评论集合(这正是 mongoose 的工作方式,我接受)。

问题:如何防止 Mongoose 创建单独的“评论”集合。在预保存方法中,我想调用next(),之后不进行任何写操作。有什么想法吗?

【问题讨论】:

    标签: node.js mongodb mongoose middleware


    【解决方案1】:

    这让我获得了 Tumbleweed 徽章……万岁!?!?

    所以我写了很多代码来完成上述工作。在进行更多测试之前,我不想发布它。但是,如果有人对此感兴趣,请在此处发帖告诉我。我很乐意交出我所拥有的(即将投入生产)。

    目前我的代码不支持深度嵌套...这意味着您只能使用类似于上面的 blog/cmets 示例的“简单”嵌套。我有合适的架构来处理将来更复杂的嵌套,但我现在没有时间进行测试(该死的最后期限)。以下是关于我的解决方案的一些要点:

    • 所有操作都需要父文档的 id(一旦开始使用就有意义)
    • findfindOnesaveremove 直接在嵌套模型上
    • findById 不(不能)工作 - 它也许可以工作,但需要搜索整个集合,这很慢。必须改用 findOne + 父 ID(参见示例)。
    • 超快 - 使用投影进行查找,并在父模型上使用 Model.update() 保存(非常快)。
    • 所有中间件仍在执行(前/后和验证)
    • findAndUpdate/Remove 方法都不起作用 [还没有?]

    设置

    // setup the "nestedSchema" plugin
    var nestedSchema = require("./plugins/nestedSchema");
    CommentSchema.plugin(nestedSchema, {
        path: 'comments',
        ownerModelPath: './BlogPostModel',  
        ownerIdFieldName: 'blogpost_id'
    });
    

    示例 - 请注意始终使用父级的 blogpost_id - 这是使其保持快速的要求(为简洁起见,删除了回调和错误处理):

    // create a new comment
    var comment = new CommentModel({
        blogpost_id: [id],
        name: 'Joe Schmoe',
        body: 'The content of the comment'
    });
    comment.save();
    
    // use findOne in leu of findById
    CommentModel.findOne({blogpost_id: [id], _id: [id]}, function( err, comment ) {
        comment.set('body', 'This comment has been updated directly!');
        comment.save();
    });
    
    // find all hateful comments and remove
    CommentModel.find({blogpost_id: [id], body: /sucks|stupid|dumb/gi}).remove();
    

    【讨论】:

      【解决方案2】:

      使用 https://www.npmjs.org/package/mongoose-relationship 的 mongoose-relationship 插件 可以让您的文件了解它们之间的关系。

      添加/删除文档时,插件会更新相应的引用。

      github页面上有一个很好的例子:https://github.com/sabymike/mongoose-relationship

      【讨论】:

      • 不确定谁投了反对票(不是我)。这个插件看起来很有趣,是我使用的技术的不同方法。您可以通过如何定义父路径和子路径(我遇到的相同问题)来查看执行此操作的所有复杂性。我不喜欢你必须如何在子架构上定义“父”路径......嘘 - 但它确实允许多个嵌套,不像我的......耶。 一种方法可以让子模式以编程方式确定他的生活位置......但这非常复杂。在有人弄清楚之前,此功能不会完成。
      猜你喜欢
      • 2018-06-23
      • 2019-03-22
      • 1970-01-01
      • 2013-07-21
      • 2021-12-25
      • 2019-12-27
      • 2014-08-04
      • 1970-01-01
      • 2014-06-22
      相关资源
      最近更新 更多