2014-09-23 169 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