3

概述

我正在创建一个使用 Facebook 登录的 Ruby on Rails 网站。

对于每个用户,我都有一个数据库条目,其中存储了他们的 Facebook 用户 ID 以及其他基本信息。

我还使用 Koala gem 从 Facebook 检索用户的好友列表,但我不确定我应该如何存储这些数据......

选项1

我可以将用户的朋友作为序列化哈希存储在User表中,然后如果我想显示所有当前用户朋友的列表,我可以抓住这个哈希并按照以下方式做一些事情SELECT FROM Users WHERE facebook_user_id IN hash

每次用户登录时,我都可以更新此字段以存储最新的朋友列表。

选项 2

我可以在这里创建一个朋友表并存储友谊信息,其中一个用户有很多朋友。所以每个友谊都会有一行,(User1User2列)。然后显示当前用户的朋友列表,我可以做类似的事情SELECT User2 FROM Friends WHERE User1 = current_user

这对我来说似乎是更好的选择,但是......

它的缺点是会有很多行……如果有 100,000 个用户,每个用户有 100 个朋友,那么现在 Friends 表中有 10,000,000 行。

这也意味着每次用户登录时,我都需要遍历他们使用 Koala 返回的 Facebook 好友列表,如果他们的好友列表中的某人在我的用户表中并且好友中没有相应的条目,则创建一个好友记录桌子。如果用户有 1000 个 Facebook 朋友,这似乎会很慢?

我将不胜感激有关如何最好地实现这一目标的任何指导。

为措辞不当的问题道歉,我会尽快尝试改写/组织它。

感谢您提前提供任何帮助。

4

1 回答 1

2

如果您需要存储大量数据,那么您需要存储大量数据。如果你和大多数人一样,你可能不会在有钱解决问题之前就遇到这个问题。换句话说,您可能会假设您将拥有比您获得的更多的流量和数据,至少在短期内是这样。所以我怀疑这是一个问题,尽管这是一个好迹象,表明你现在而不是以后考虑它。

正如我在下面的评论中提到的,最简单的解决方案是为好友关系的每一方设置一个平局表(has_many :friends, through: :facebook_friend_relationships, class_name: 'FacebookFriend'FacebookFriend 上的一个,根据下面提到的设计)。但是你的问题似乎是关于如何减少记录的数量,所以这就是答案的其余部分要解决的问题。

如果您必须存储在数据库中,并且您确定您肯定会让地球上的每个 FB 用户访问您的网站,因为它太棒了,但他们不会一次全部访问,那么如果您的存储空间有限,您可能还想使用 LRU 算法(删除最近最少使用的记录),也可能带有定时到期。您可以有一个 cron 作业,在数据库上执行查询,然后删除旧/未使用的记录来执行此操作。不会是完美的,但这将是一个简单的解决方案。

您还可以归档旧数据而不是将其丢弃。因此,经常使用的数据可能会保留在活动用户表中,然后您可能会将旧数据卸载到另一个表甚至另一个数据库(您可能会为此看到公寓和 second_base 宝石)。但是,一旦确定了规模,您可能会考虑一些与 ActiveRecord 模型/关联或模式设计关系不大的其他架构解决方案。尽管提前计划是值得的,但在您确定应用程序将获得足够多的用户来投入时间之前,我不会过度担心这一点。

即使 ActiveRecord 有一些缓存,您也可以在一开始就避免使用数据库并将朋友缓存在内存中以提高速度,尤其是在您还没有很多用户的情况下,您可能还没有。如果您认为由于大量用户而导致内存不足,LRU 在这里也可能是一个不错的选择,而且lru_redux看起来很有趣。同样,您可能希望缓存也过期并在缓存过期时重新获得朋友。即使只是将结果存储在用户会话中也可能就足够了,即在控制器操作方法中,只是 do @friends ||= Something.find_friends(fb_user_id),而后者是大多数人在开始时可能会做的第一次尝试。

如果您使用 ActiveRecord,请在控制器中的查询(或模型中的关联)中考虑使用include:以避免 n+1 查询。这将加快速度。

对于架构设计,也许:

  • 用户 - 包含电子邮件和身份验证信息的用户表。看看设计宝石。
  • FacebookUser - 关于 Facebook 用户的信息。
  • FacebookFriendRelationship - 具有(id 和)两列的关系模型,一列用于一个 FacebookUser id,另一列用于另一列。

通过将 authN 信息(用户)与 FB 数据(FacebookUser 和 FacebookFriendRelationship)分开,您可以更轻松地拥有其他社交媒体帐户等,每个帐户在其他表中都包含特定于这些帐户的信息。

如果目标是最小化关系表中的行,那么复杂性来自 FacebookUser 与朋友的关系。对于一半的行数,您将有一行用于 FacebookUser 的 id 可以在任一外键列中的关系。用户有朋友或者是朋友,所以你可以有两个has_many :throughFacebookFriend 上的关联,每个关联在 FacebookFriendRelationship 中使用不同的外键。或者您可以在没有模型的情况下执行 HABTM,并在每个关联中使用 foreign_key 和 association_foreign_key 选项。无论哪种方式,您都可以添加一个方法来将两个关联添加在一起(因为它们是数组)。相反,如果您不关心必须使用 ActiveRecord 以正常方式删除关联,则可以在单个 has_many 中使用自定义 SQL。但是,根据您的评论,我认为您希望避免这种复杂性,并且我同意您的观点,除非您确实必须限制关系行的数量。然而,吃掉数据的不是关系表的行数,而是你保存在 FacebookFriends 表中的所有用户信息。

于 2013-05-16T22:06:31.990 回答