【问题标题】:Searching embedded documents Mongoose + nodejs搜索嵌入文档 Mongoose + nodejs
【发布时间】:2011-09-06 05:16:43
【问题描述】:

我是 Mongoose 的新手,我在搜索时遇到了问题。

这些是我的架构:

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

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

cmets 嵌套很深。当有人回答现有评论时,我怎样才能找到那个?

【问题讨论】:

    标签: mongodb node.js mongoose


    【解决方案1】:

    您可以查看 github 上的 mongoose 测试套件以获取示例。

    model_querying_test

    这是您要查找的内容:

    基于嵌入文档字段的测试结果:

    function () {
        var db = start(), BlogPostB = db.model('BlogPostB', collection);
    
        BlogPostB.create({comments: [{title: 'i should be queryable'}]}, function (err, created) {
          should.strictEqual(err, null);
          BlogPostB.findOne({'comments.title': 'i should be queryable'}, function (err, found) {
            should.strictEqual(err, null);
            found._id.should.eql(created._id);
            db.close();
          });
        });
        },
    

    【讨论】:

    • 但是这个搜索只针对一个嵌套级别。如果我有很深的嵌套结构并且我想找到Blog { comments { comments { comments {this comment} }}} 并且每次我想找到评论我都不知道有多少嵌套级别。
    • 但是等等...他们有相同的结构Comments.add({ comments : [Comments] });让我试试
    • 不,它没有找到它。猜猜我需要手动搜索它。关键是我不知道“正确的方法”。如果手动搜索,比如for(i=0...){if (hasComments) recursive()},是“正确”的方式,所以我会这样做。我只是不知道是否有更简单的方法。 p.s.无论如何 FindOne 方法会找到帖子,而不是评论..
    • findOne 方法将始终返回顶级文档,在这种情况下为 Post - 如果您想直接提取评论文档,您必须将它们放在自己的顶级文档中并通过链接ObjectId,请参阅下面的答案以了解如何执行此操作。
    【解决方案2】:

    对此的一种解决方案是将评论存储为可以直接查询的单独模型,并存储对相关 ObjectId 的引用以及评论和帖子之间的路径。

    在 Mongoose 相关文档中使用 Populate 功能的功能与嵌入文档类似,尽管在查询它们的方式上存在一些重要差异,并且您必须更加小心地保持关系填充。

    这样设置:

    var mongoose = require('mongoose')
      , Schema = mongoose.Schema
      , ObjectId = Schema.Types.ObjectId;
    
    var PostsSchema = new Schema({
      body     : String,
      stories  : [{ type: ObjectId, ref: 'Story' }]
    });
    
    var CommentsSchema = new Schema({
      body     : String,
      post     : { type: ObjectId, ref: 'Post' },
      comments : [{ type: ObjectId, ref: 'Comment' }]
    });
    
    var Story   = mongoose.model('Post', PostsSchema);
    var Comment = mongoose.model('Comment', CommentsSchema);
    

    如果您这样做,则需要更多查询才能获取包含所有 cmets 的帖子(这将比使用单个查询加载帖子及其完整的评论层次结构要慢)但是您将能够直接查询 cmets 并检索他们发表的帖子(但在嵌套时不容易找到评论的完整路径)。

    这些都是取舍;最好的决定(递归搜索 cmets,或者独立存储它们然后递归加载它们)应该在您的应用程序及其预期使用模式的上下文中做出。

    另一个警告;填充功能目前仅限于单级链接的 ObjectId;您必须在返回的每个评论上调用它以获取完整的嵌套数据集。有几个插件可以帮助解决这个问题,例如 mongoose-subpopulate,很快它就会在 Mongoose 中得到原生支持 - 请参阅 github issue here。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2011-12-14
      • 2012-02-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-07-17
      • 2012-02-18
      相关资源
      最近更新 更多