2013-05-16 20 views
3

概述在我的數據庫中存儲用戶的Facebook朋友列表的最佳方式是什麼?

我創建了一個使用Facebook登錄的Ruby on Rails網站。

對於每個用戶,我都有一個數據庫條目,用於存儲他們的Facebook用戶ID以及其他基本信息。

我還使用了考拉的寶石,以獲取來自Facebook用戶的好友列表,但我不確知我應該如何存儲這些數據...

選項1

我可以在User表中存儲用戶的朋友作爲序列化哈希,然後如果我想顯示所有當前用戶的朋友列表,我可以抓住這個哈希並按照SELECT FROM Users WHERE facebook_user_id IN hash

用戶登錄我可以更新這個f可以存儲最新的朋友列表。

選項2

我可以在這裏創建一個朋友表和存儲友誼的信息,在用戶有很多朋友。所以每個友誼都會有一排(User1User2列)。然後,顯示當前用戶的好友列表,我可以做類似SELECT User2 FROM Friends WHERE User1 = current_user

這似乎是一個更好的選擇我,但是......

它的缺點是會有很多的行...如果有100,000個用戶,每個用戶有100個朋友,那麼Friends表中現在有10,000,000個行。

這也意味着每次用戶登錄時,我需要遍歷他們的Facebook朋友列表返回使用考拉和創建一個朋友記錄,如果他的朋友列表中有人在我的用戶表中,並沒有一個相應的進入朋友表。這似乎是如果一個用戶有1000個Facebook的朋友會很慢?

我很感激任何指導如何最好的實現這一目標。

對措辭嚴厲的問題表示歉意,我會盡快嘗試重新組織。

感謝您提前提供任何幫助。

回答

2

如果您需要存儲大量數據,那麼您需要存儲大量數據。如果你像大多數人一樣,你可能不會很快遇到這個問題,而不是現金來解決問題。換句話說,您可能會認爲您的流量和數據會比您獲得的流量和數據更多,至少在短期內是如此。所以我懷疑這是一個問題,即使這是一個好兆頭,你現在正在考慮它,而不是以後。

正如我在我下面的評論中提到,最簡單的解決辦法是有領帶表,一排的朋友關係的各側(FacebookFriend一個has_many :friends, through: :facebook_friend_relationships, class_name: 'FacebookFriend',根據設計下面提到)。但是你的問題似乎是關於如何減少記錄數量,所以答案的其餘部分將解決這個問題。

如果您必須存儲在數據庫中,並且您確信您絕對會讓地球上的每個FB用戶都擊中您的站點,因爲它非常棒,但它們不會一次全部擊中,那麼如果您在存儲方面受到限制,您可能希望使用LRU算法(刪除最近最少使用的記錄),並且可能也會使用定時到期。你可能只需要一個cron作業,在數據庫上執行一個查詢,然後刪除舊/未使用的記錄來執行此操作。不完美,但它會是一個簡單的解決方案。

您也可以將舊數據存檔而不是將其丟棄。因此,經常使用的數據可能會留在活動用戶的表中,然後您可能會將舊數據卸載到另一個表或甚至另一個數據庫(您可能會看到公寓和second_base的寶石)。然而,一旦你達到了規模,你可能會看到許多與ActiveRecord模型/關聯或模式設計相關的架構解決方案。雖然提前計劃是值得的,但我不會過分擔心,直到您確信應用程序將獲得足夠的用戶來投入時間。

儘管ActiveRecord有一些緩存,但您可以避免使用數據庫並緩存內存中的朋友,因爲速度起步時尤其如此,尤其是如果您還沒有很多用戶時,您可能還沒有。如果您認爲由於用戶數量太多而導致內存不足,那麼LRU可能也是一個不錯的選擇,並且lru_redux看起來很有趣。同樣,您可能想要在高速緩存到期時也使緩存過期並重新獲得朋友。即使只是將結果存儲在用戶會話中也是適用的,即在控制器操作方法中,只需執行@friends ||= Something.find_friends(fb_user_id),而後者是您在開始時的第一步操作。

如果您使用ActiveRecord,請在您的控制器查詢中(或關於模型中的關聯)考慮使用include:以避免n + 1個查詢。這會加速事情。

對於架構設計,也許:

  • 用戶 - 電子郵件和authN信息的用戶表。看看設計的寶石。
  • FacebookUser - 有關Facebook用戶的信息。
  • FacebookFriendRelationship - 具有(id和)兩列的領帶模型,一個用於一個FacebookUser ID,另一個用於另一個。

通過分離從FB數據(FacebookUser和FacebookFriendRelationship)的authN信息(用戶),你更容易有其他社交媒體帳戶等,它們各具到其他表中的帳戶的信息。

如果目標是最小化關係表中的行,那麼FacebookUser與朋友的關係就會變得複雜。對於行數的一半,您將有一行關於FacebookUser的id可以在任何外鍵列中的關係。無論用戶有朋友還是朋友,所以您可以在FacebookFriend上擁有兩個has_many :through關聯,每個關聯在FacebookFriendRelationship中使用不同的外鍵。或者,您可以在沒有模型的情況下執行HABTM,並在每個關聯中使用foreign_key和association_foreign_key選項。無論哪種方式,您都可以添加一個方法將兩個關聯添加在一起(因爲它們是數組)。相反,如果您不需要使用ActiveRecord以正常方式刪除關聯,則可以在單個has_many中使用自定義SQL。但是,根據您的意見,我認爲您想避免這種複雜性,並且我同意您的看法,除非您真的必須限制關係行的數量。但是,這並不是綁定錶行數量會佔用數據,它將成爲您在FacebookFriends表中保留的所有用戶信息。

+0

感謝您的回答。你是對的,從來沒有這麼多的用戶,我只是想學習最好的方式去做事情。如果我按照您建議的模式行事,每次用戶登錄時,我都需要更新關係表,以便爲自上次訪問以來已註冊到我的網站的任何用戶的朋友創建友誼。這將需要遍歷他們的朋友列表並嘗試在我的數據庫中找到用戶,如果存在,則創建一個新的關係條目(如果尚未存在的話)。這是做事最有效的方式嗎?這看起來效率很低。 – woodstock365

+0

你的目標似乎是減少記錄(根據你在問題中10,000,000行的例子),所以對於每一個關係來說,對於同一關係的每個方向有一個記錄,對於每個方向有一個記錄會有一半的行數(所以會是5000000)。但是,如果您不介意每個關係都有可能重複的行,那對您當前的需求來說似乎是更好的解決方案。 –

+0

另外,你不是(或者至少不應該)在控制器中進行循環以獲得每個朋友。你的查詢和數據庫是(希望)在這方面很好。爲了避免你所指的n + 1個查詢,使用':include'選項來確保AR查詢的時間,它只爲每個模型類型查詢一次查詢。你可以優化這個更多,但在一開始,你可能不需要。 –

相關問題