让mongoose模型意识到它是嵌套的

时间:2014-05-17 00:41:19

标签: node.js mongodb mongoose middleware

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

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

我了解如何为博客帖子添加,更新和删除评论,但所有这些方法都需要在父博客帖子文档中调用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(),之后不进行任何写操作。有什么想法吗?

2 个答案:

答案 0 :(得分:2)

这为我赢得了Tumbleweed徽章......万岁!?!?

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

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

  • 所有操作都需要父文档的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();

答案 1 :(得分:0)

使用https://www.npmjs.org/package/mongoose-relationship中的mongoose-relationship插件 可以使您的文档了解他们的关系。

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

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