简体   繁体   English

了解猫鼬子文档

[英]Understanding Mongoose sub documents

I'm learning Mongoose. 我正在学习猫鼬。 At the moment I did few nice things but I really don't understand exactly how Mongoose manage relationships between Schemas. 目前,我没有做过很多不错的事情,但是我真的不完全了解Mongoose如何管理架构之间的关系。

So, easy thing (I hope): I'm doing a classic exercise (by my self because I cannot find a good tutorial that create more than 2 Schemas) with 3 Schemas: 因此,一件简单的事(我希望):我正在做一个经典的练习(我自己,因为我找不到能创建两个以上架构的优秀教程),其中包含3个架构:

User, Post, Comment. 用户,帖子,评论。

  • User can create many Post; 用户可以创建多个帖子;
  • User can create many Comment; 用户可以创建许多评论;
  • Post belong to User. 帖子属于用户。
  • Comment belong to User and Post. 评论属于用户和帖子。

I don't think it is something very hard uhu? 我不觉得这很困难吗?

At the moment I can manage very well Relation between User and Post. 目前,我可以很好地处理用户与帖子之间的关系。 My Unit test return exactly what I need, at the moment I'm using mongo-relation and I don't know if it is a good idea... 我正在使用mongo-relation时 ,我的单元测试恰好返回了我需要的结果,我不知道这是否是个好主意...

  it('Use should create a Post', function(done) {
    User.findOne({ email: 'test@email.com' }, 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();
      });
    });
  });

The problem now is to create a comment. 现在的问题是创建评论。 I can not create a comment that refere to the Post and to the User together. 我无法创建同时引用帖子和用户的评论。

I did something like that and works but when I perform a remove it is removed only from the Post and not from the User. 我做了类似的事情并且可以工作,但是当我执行remove它只会从发布中删除,而不会从用户中删除。

So I think there is something I miss or I still need to study to enhance it. 因此,我认为有些事情我想念的,或者我仍然需要学习以增强它。

  it('User should add a Comment to a Post', function(done) {
    User.findOne({ email: 'test@email.com' }, 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();
        });
      });
    });
  });

As you can see the code is not very "nice to see" but it works fine in terms of creations. 如您所见,该代码不是很“好看”,但就创作而言,它可以很好地工作。

The problem is when I remove a Comment. 问题是当我删除评论时。 It seems like something is wrong. 好像有什么问题。

Here is the Model relationship: 这是模型关系:

// 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
});

I really hope in your help to understand all this. 我真的希望您能帮助您理解所有这一切。

It will be nice also a simple good tutorial about it. 一个很好的简单教程也不错。

I think you are misunderstanding subdocuments. 我认为您是对子文档的误解。 The way you have your schema setup you are creating references to documents in other collections. 建立架构的方式是创建对其他集合中文档的引用。

For example if you create a post, in the database it will look like this: 例如,如果您创建一个帖子,则在数据库中它将如下所示:

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

Notice the "author" field just contains the ID of the author who created it. 请注意,“作者”字段仅包含创建它的作者的ID。 It does not actually contain the document itself. 它实际上并不包含文档本身。

When you read the document from the DB you can use the mongoose 'populate' functionality to also fetch the referred to document. 从数据库读取文档时,可以使用猫鼬的“填充”功能来获取所引用的文档。

Ex (with populate): 防爆(填充):

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

Ex (no populate): 防爆(无填充):

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

Subdocuments: 子文档:

You can actually nest data in the DB using subdocuments, the schema would look slightly different: 您实际上可以使用子文档将数据嵌套在数据库中,该架构看起来会稍有不同:

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

When saving a post the user document would be nested inside the post: 保存帖子时,用户文档将嵌套在帖子中:

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

Subdocuments can be useful in mongo, but probably not for this case because you would be duplicating all of the user data in every post. 子文档在mongo中可能很有用,但可能不适用于这种情况,因为您将在每个帖子中复制所有用户数据。

Removing documents 移除文件

When you issue a Comment.remove(id) the comment will be removed but it will not affect the other documents referring to it. 当您发布Comment.remove(id)时,该注释将被删除,但不会影响引用该注释的其他文档。 So you will then have a Post and a User with a comment ID that does not exist. 因此,您将拥有一个帖子和一个用户,该用户的评论ID不存在。 You need to manually clean up the comment ID from the other documents. 您需要手动清除其他文档中的注释ID。 You could use the mongoose pre remove event to do this. 您可以使用猫鼬预删除事件来执行此操作。 http://mongoosejs.com/docs/middleware.html 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();
    });
  });
});

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM