2014-09-23 168 views
1

我正在学习猫鼬。目前我做了几件不错的事情,但我真的不明白Mongoose如何管理Schema之间的关系。了解猫鼬子文档

所以,容易的事情(我希望):我在做一个经典的运动(由我自己,因为我无法找到创建2个以上架构一个很好的教程)3层架构:

用户,邮政,评论。

  • 用户可以创建多个Post;
  • 用户可以创建很多评论;
  • 帖子属于用户。
  • 评论属于用户和帖子。

我不认为这是非常难呃?

目前我可以很好地管理用户和发布之间的关系。我的单元测试的回报正是我需要的,此刻我使用mongo-relation,我不知道这是否是一个好主意......

it('Use should create a Post', function(done) { 
    User.findOne({ email: '[email protected]' }, function(err, user) { 
     var post = { 
     title: 'Post title', 
     message: 'Post message', 
     comments: [] 
     }; 
     user.posts.create(post, function(err, user, post) { 
     if (err) return done(err); 
     user.posts[0].should.equal(post._id); 
     post.author.should.equal(user._id); 
     // etc... 
     done(); 
     }); 
    }); 
    }); 

现在的问题是创建一个注释。 我无法创建一个引用帖子和用户在一起的评论。

我做了类似的工作,但是当我执行remove时,它仅从帖子中删除,而不是从用户删除。

所以我觉得有一些我很想念,或者我仍然需要学习来加强它。

it('User should add a Comment to a Post', function(done) { 
    User.findOne({ email: '[email protected]' }, function(err, user) { 
     if (err) return done(err); 

     var comment = new Comment({ 
     author: user._id, 
     message: 'Post comment' 
     }); 

     Post.findOne({ title: 'Post title'}, function(err, post) { 
     if (err) return done(err); 
     post.comments.append(comment, function(err, comment) { 
      if (err) return done(err); 

      post.save(function(err) { 
      if (err) return done(err); 
      }); 

      comment.author.should.equal(user._id); 
      post.comments.should.have.length(1); 
      // etc... 
      done(); 
     }); 
     }); 
    }); 
    }); 

正如你所看到的代码不是很高兴看到的,但它在创作方面效果很好。

问题是当我删除评论。看起来有些事情是错的。

这里是Model关系:

// User Schema 
var userSchema = new mongoose.Schema({ 
    // [...], 

    posts: [{ type: mongoose.Schema.Types.ObjectId, ref: 'Post' }], 
    comments: [{ type: mongoose.Schema.Types.ObjectId, ref: 'Comment' }], 

}); 

// Post Schema 
var postSchema = new mongoose.Schema({ 
    author: { type: mongoose.Schema.ObjectId, ref: 'User', refPath: 'posts' }, 
    title: String, 
    message: String, 
    comments: [{ type: mongoose.Schema.ObjectId, ref: 'Comment' }] 
}); 

// Comment Schema 
var commentSchema = new mongoose.Schema({ 
    author: { type: mongoose.Schema.ObjectId, ref: 'User', refPath: 'comments' }, 
    post: { type: mongoose.Schema.ObjectId, ref: 'Post', refPath: 'comments' }, 
    message: String 
}); 

在你的帮助,我真的很希望了解这一切。

这也将是一个很好的教程关于它。

+0

而你如何删除它? – Vinz243 2014-09-23 14:28:56

+0

Comment.remove(id) – 2014-09-24 08:07:57

回答

1

我认为你误解了子文档。您拥有模式设置的方式是创建对其他集合中文档的引用。

例如,如果您创建一个职位

,在数据库中它看起来就像这样:

{ 
    "author": ObjectId(123), 
    "title": "post title", 
    "message": "post message", 
    "comments": [ObjectId(456), ObjectId(789)] 
} 

通知“作者”字段只包含谁创造了它的作者的ID。它实际上并不包含文档本身。

当您从数据库中读取文档时,您可以使用猫鼬'填充'功能来获取所引用的文档。

EX(与已安装):

Post 
    .findOne({ title: 'Post title'}) 
    .populate('author', function(err, post) { 
    // this will print out the whole user object 
    console.log(post.author) 
    }); 

EX(没有填入):

Post 
    .findOne({ title: 'Post title'}, function(err, post) { 
    // this will print out the object ID 
    console.log(post.author) 
    }); 

子文档:

实际上,你可以使用子文档时,在DB巢数据模式看起来稍有不同:

var postSchema = new mongoose.Schema({ 
    author: { userSchema }, 
    title: String, 
    message: String, 
    comments: [commentSchema] 
}); 

当保存后的用户文件将被嵌套在门柱内侧:

{ 
    "author": { 
    "name": "user name", 
    "email": "[email protected]" 
    ... 
    }, 
    "title": "post title", 
    "message": "post message", 
    "comments": [{ 
    "message": "test", 
    ... 
    }, { 
    "message": "test", 
    ... 
    }] 
} 

子文档可以在蒙戈有用的,但可能不是这种情况,因为你会被复制所有用户数据的每帖子。

删除文件

当您发出Comment.remove(ID)的评论将被删除,但它不会影响到其他文件引用它。因此,您将有一个帖子和一个用户,其评论ID不存在。您需要手动清理其他文档中的评论ID。你可以使用mongoose预删除事件来做到这一点。 http://mongoosejs.com/docs/middleware.html

commentSchema.pre('remove', function (next) { 
    // this refers to the document being removed 
    var userId = this.author; 
    var postId = this.post; 

    User.findById(userId, function(err, user) { 

    // remove comment id from users.comments here; 

    Post.findById(postId, function(err, post) { 

     // remove comment id from post.comments; 

     next(); 
    }); 
    }); 
}); 
+0

我知道这一点,我希望只有我的ID,而不是复制整个用户文档...随着填充我可以得到我需要的所有属性。 – 2014-09-24 08:07:09

+0

刚刚更新了我的答案,提供了有关删除文档的一些详细信息 – mattetre 2014-09-24 21:43:04

+0

感谢您的更新,这很有道理,但是如何从评论架构获取用户ID和发布ID?你能提供一个更深的例子吗?谢谢 – 2014-09-26 09:02:35