注:本文使用sequelize 1.7.0。所舉例子均已通過測試,可以放心使用。
使用sequelize能夠較為方便的按照MVC模式組織nodejs程序后端架構。這篇文章,就筆者認為,其中較為有用且稍有難度的association進行分享。
通常,模型之間共有三種關系,1:1,1:n,n:m。以下舉例逐個擊破。
1:1.假如有user和userinfo倆個模型,分別對應用戶,以及用戶的資料。此時,每個用戶應當有且只有一個用戶資料,由此,user與uerinfo的關系應當為1:1.在sequelize中,使用hasOne與belongsTo進行描述。在實際的模型中
1 // in User model 2 associate: function(models){ 3 User. hasOne(models.UserInfo); 4 } 5 //in UserInfo model 6 associate: function(models){ 7 UserInfo.belongsTo(models.User); 8 }
上邊這段代碼中,講的就是,一個User有一個UserInfo,一個UserInfo反過來屬於一個User。由此雙方關系確立。運行代碼后,sequelize會自動在UserInfo中增加一個外鍵UserId.在搜索的時候如果需要獲取UserInfo,可以使用下面倆種方式:
1 models.User.findOne({ 2 where:{ id: userid }, 3 include: {model: models.UserInfo, as: 'Info'} 4 }).then(function(user){ 5 /*{ 6 name: 'xxx', 7 UserInfo: { 8 email: 'xxx' 9 } 10 11 }*/ 12 }); 13 models.User.findOne({ 14 where:{id: id} 15 }).then(function(user){ 16 user.getUserInfo().then(function(info){ 17 /*{ 18 email:'xxx', 19 sex: 'male', 20 profile: 'usl:xxx' 21 } 22 */ 23 }) 24 });
1:n.假如一個人要發博客,那么一個人User應當會發很多篇博文Article,這樣User和Article之間的關系就可以恰當的表示為1:n。類比1:1的描述方式,sequelize中使用hasMany與belongsTo進行表示。代碼與1:1中雷同,就此不再啰嗦。
n:m。這個相比前倆者而言是較為復雜的,講解這個實際上是這篇博文的主要目的所在。為了更為全面深入的講解,特別舉一個非常復雜的例子。倆個模型分別為用戶User和文章Topic。他們之間的關系有:(1:n)用戶寫了很多篇文章,每個文章只有一個作者;(n:m)假如有收藏功能,用戶會收藏一些文章,每篇文章也會被很多人所收藏。本來就此就可以了,但是為了增加復雜度,特地再引入一種n:m關系,文章被用戶所評價。sequelize是使用belongsToMany來表示n:m的關系的。在這種多對多的關系中,特別像本文這種情況,有多種多對多關系,為了更為清晰的描述,通常會引入另外一張關系表。具體請參考如下代碼:
1 /*in User model*/ 2 associate: function(models) { 3 User.hasMany(models.Topic, {as: 'AuthorTopics', foreignKey: 'authorId'}); 4 User.belongsToMany(models.Topic, {as: 'WatchedTopics', through: 'UserWatchedTopic'}); 5 User.belongsToMany(models.Topic, {as: 'CommentedTopics', through: models.UserCommentTopic}); 6 } 7 /*in Topic*/ 8 associate: function(models) { 9 Topic.belongsTo(models.User, {as: 'Author', foreignKey: 'authorId'}); 10 Topic.belongsToMany(models.User, {as: 'Watchors', through: 'UserWatchedTopic'}); 11 Topic.belongsToMany(models.User, {as: 'Commenters', through: models.UserCommentTopic}); 12 }
上述倆種n:m關系分別使用了倆張表UserWatchedTopic, UserCommentTopic來描述。UserWatchedTopic直接使用字符串,適用於簡單的多對多關系。當我們想記錄這種n:m的關系中一些二外的信息,比如,當前想把第一種是否為作者合並到n:m得關系中,此時可在UserCommentTopic中增加isAuthor字段進行標記。當然,筆者認為這樣會使得關系復雜化,損害腦細胞。
假如我們要獲取一篇文章的關注者時,可以這樣:
1 models.Topic.findOne({ 2 where: {id: id} 3 }).then(function(topic){ 4 topic.getWatchors().then(function(watchers){ 5 /* 6 [{watcher1}{watcher2}{watcher3}] 7 */ 8 }) 9 })
That's it.
如有疑問,歡迎隨時討論。fangbolang@163.com