2015-04-29 49 views
3

我正在研究一個簡單的應用程序,其中用戶可以關注其他用戶。用戶可以明星的帖子。而用戶的Feed由由他們關注用戶加星標的帖子組成。其實很簡單。然而,這一切都變得複雜在蒙戈和流星......建模併發布基於追隨者的流星

有這個造型的兩種基本方式,我能想到的:

  1. 用戶有一個屬性,following,這是一個數組用戶遵循的用戶ID。另外,一個帖子有一個屬性starrers,它是一個userIds數組,它已經爲此帖添加了主角。關於這種方法的好處是,出版物都相對簡單:

    Meteor.publish 'feed', (limit) -> 
        Posts.find({starrers: {$in: Meteor.users.findOne(@userId).following}}, {sort: {date: -1}, limit:limit}) 
    

    我們不是被動地傾聽用戶是繼誰,但那不是太糟糕了。這種方法的主要問題是(1)如果100萬人出任職位,單個文件將變得龐大且效率低下。另一個問題是(2)跟蹤信息是很痛苦的,例如用戶何時開始關注另一個用戶或者何時用戶出現了帖子。

  2. 這樣做的另一種方式是有兩個更多的收藏StarsFollows。如果用戶對某個帖子進行了演示,那麼我們將創建一個文檔,其中包含屬性userIdpostId。如果用戶關注另一個用戶,則我們創建一個文檔,其中包含屬性userIdfollowId。這爲我們帶來了優勢,即UsersPosts的文檔尺寸較小,但在查詢時會遇到複雜的問題,尤其是因爲Mongo不處理連接!

現在,我做了一些研究,人們似乎同意第二種選擇是正確的方式。現在我遇到的問題是高效查詢和發佈。根據Discover Meteor chapter about Advanced Publications,我創建了一個發佈,發佈由用戶的關注者加星標的帖子 - 排序和限制。

# a helper to handle stopping observeChanges 
observer = (sub, func) -> 
    handle = null 
    sub.onStop -> 
    handle?.stop?() 
() -> 
    handle?.stop?() 
    handle = func() 


Meteor.publish 'feed', (limit) -> 
    sub = this 
    userId = @userId 

    followIds = null 
    eventIds = null 

    publishFollows = observer sub,() -> 
    followIds = {} 
    Follows.find({userId:userId}).observeChanges 
     added: (id, doc) -> 
     followIds[id] = doc.followId 
     sub.added('follows', id, doc) 
     publishStars() 
     removed: (id) -> 
     delete followIds[id] 
     sub.removed('follows', id) 
     publishStars() 

    publishStars = observer sub,() -> 
    eventIds = {} 
    Stars.find({userId: {$in: _.keys(followIds)}).observeChanges 
     added: (id, doc) -> 
     eventIds[id] = null 
     sub.added('stars', id, doc) 
     publishEvents() 
     removed: (id) -> 
     delete eventIds[id] 
     sub.removed('stars', id) 
     publishEvents() 

    publishEvents = observer sub,() -> 
    Events.find({_id: {$in: _.keys(eventIds)}}, {sort: {name:1, date:-1}, limit:limit}).observeChanges 
     added: (id, doc) -> 
     sub.added('events', id, doc) 
     changed: (id, fields) -> 
     sub.changed('events', id, fields) 
     removed: (id) -> 
     sub.removed('events', id) 

雖然這個工作,它似乎非常有限的規模。特別是,我們必須編輯每個追隨者每個星標的列表。這個列表的大小將會很快增長。然後,我們對所有帖子做一個巨大的$in查詢。

另一個煩惱是查詢我們同意後在客戶端上飼料:

Meteor.subscribe("feed", 20) 
posts = null 
Tracker.autorun -> 
    followers = _.pluck(Follows.find({userId: Meteor.userId()}).fetch(), "followId") 
    starredPostIds = _.pluck(Stars.find({userId: {$in: followers}}).fetch(), "postId") 
    posts = Posts.find({_id: {$in: starredPostIds}}, {sort: {date: -1}, limit: 20}).fetch() 

它就像我們正在做這一切工作的兩倍。首先,我們在服務器上完成所有工作,以發佈供稿。然後,我們需要再次在客戶端上完成相同的邏輯以獲得這些帖子...

我的問題在這裏是一切設計問題。 如何根據追隨者凝視帖子來有效地設計此饋送?我應該使用什麼樣的收集/收集模式?我應該如何創建適當的出版物?我如何查詢客戶端上的Feed?

回答

0

所以事實證明,Mongo和「非關係型」數據庫根本不是爲關係型數據設計的。因此,Mongo並沒有解決這個問題。我已經結束了使用Neo4j,但SQL也會很好地工作。

0

meteor add reywood:publish-composite

Meteor.publishComposite('tweets', function(username) { 
    return { 
    find: function() { 
     // Find the current user's following users 
     return Relationships.find({ follower: username }); 
    }, 
    children: [{ 
     find: function(relationship) { 
     // Find tweets from followed users 
     return Tweets.find({user: relationship.following}); 
     } 
    }] 
    } 
}); 

Meteor.publish('ownTweets', function(username) { 
    return Tweets.find({user: username}); 
});