我正在研究一個簡單的應用程序,其中用戶可以關注其他用戶。用戶可以明星的帖子。而用戶的Feed由由他們關注用戶加星標的帖子組成。其實很簡單。然而,這一切都變得複雜在蒙戈和流星......建模併發布基於追隨者的流星
有這個造型的兩種基本方式,我能想到的:
用戶有一個屬性,
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)跟蹤信息是很痛苦的,例如用戶何時開始關注另一個用戶或者何時用戶出現了帖子。
這樣做的另一種方式是有兩個更多的收藏
Stars
和Follows
。如果用戶對某個帖子進行了演示,那麼我們將創建一個文檔,其中包含屬性userId
和postId
。如果用戶關注另一個用戶,則我們創建一個文檔,其中包含屬性userId
和followId
。這爲我們帶來了優勢,即Users
和Posts
的文檔尺寸較小,但在查詢時會遇到複雜的問題,尤其是因爲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?