概述
我正在创建一个使用Facebook登录的Ruby on Rails网站。
对于每个用户,我都有一个数据库条目,用于存储他们的Facebook用户ID以及其他基本信息。
我也在使用Koala gem来从Facebook检索用户的好友列表,但我不确定应该如何存储这些数据......
选项1
我可以将用户的朋友存储为User
表中的序列化哈希值,然后如果我想显示所有当前用户的朋友列表,我可以抓住这个哈希并执行{{ {1}}
每次用户登录时,我都可以更新此字段以存储最新的好友列表。
选项2
我可以在这里创建一个朋友表并存储友情信息,其中用户有很多朋友。因此,每个友谊都会有一行(SELECT FROM Users WHERE facebook_user_id IN hash
和User1
列)。然后,要显示当前用户的朋友列表,我可以执行User2
对我来说这似乎是更好的选择,但是......
它的缺点是会有很多行...如果有100,000个用户,每个有100个朋友,那么现在在Friends表中有10,000,000行。
这也意味着每次用户登录时,我都需要循环使用Koala返回的Facebook好友列表,并创建好友记录,如果他们的好友列表中有人在我的用户表中并且没有相应的条目在朋友表中。如果用户有1000个Facebook好友,这似乎会很慢?
我很感激有关如何实现这一目标的任何指导。
对措辞严厉的问题表示歉意,我会尽快重新/组织它。
感谢您提前提供任何帮助。
答案 0 :(得分:2)
如果您需要存储大量数据,则需要存储大量数据。如果你最喜欢,你可能不会比现金解决它更快遇到这个问题。换句话说,您可能假设您拥有的流量和数据将超过您的流量和数据,至少在短期内如此。所以我怀疑这是一个问题,尽管这是一个很好的迹象,表明你现在而不是后来考虑它。
正如我在下面的评论中提到的,最简单的解决方案是在朋友关系的每一侧都有一个带有一行的关系表(FacebookFriend上的has_many :friends, through: :facebook_friend_relationships, class_name: 'FacebookFriend'
,按照下面提到的设计)。但你的问题似乎是如何减少记录的数量,这就是答案的其余部分将解决的问题。
如果你必须存储在数据库中,你肯定知道你绝对会让这个星球上的每个FB用户都击中你的网站因为它太棒了,但它们不会立刻全部命中,那么如果你是如果存储空间有限,您可能希望使用LRU算法(删除最近最少使用的记录),也可能使用定时到期。您可以只有一个cron作业对DB执行查询,然后删除旧的/未使用的记录来执行此操作。不完美,但这将是一个简单的解决方案。
您还可以归档旧数据,而不是将其丢弃。因此,经常使用的数据可以保留在活动用户的表中,然后您可以将旧数据卸载到另一个表甚至另一个数据库(您可能会看到该公寓和second_base的宝石)。但是,一旦达到规模,您可能会看到许多与ActiveRecord模型/关联或模式设计关系不大的其他架构解决方案。虽然提前计划是值得的,但我不会过分担心,直到你确定该应用程序将有足够的用户投入时间为止。
即使ActiveRecord有一些缓存,你也可以在开始时尽量避免数据库并在内存中缓存朋友的速度,特别是如果你还没有很多用户,你可能还没有。如果您认为由于用户数量众多而导致内存不足,那么LRU也可能是一个不错的选择,lru_redux看起来很有趣。同样,您可能希望将缓存计时也过期,并在缓存过期时重新获取朋友。即使只是将结果存储在用户会话中也可能是足够的,即在控制器操作方法中,只需执行@friends ||= Something.find_friends(fb_user_id)
,而后者是大多数人可能会在您开始时作为第一次拍摄时所做的事情。 / p>
如果您使用ActiveRecord,请在控制器中的查询中(或模型中的关联)考虑使用include:
来避免n + 1个查询。这样可以加快速度。
对于架构设计,可能:
通过将身份验证信息(用户)与FB数据(FacebookUser和FacebookFriendRelationship)分开,您可以更轻松地拥有其他社交媒体帐户等,每个帐户都包含其他表格中特定于这些帐户的信息。
如果目标是最小化关系表中的行,则复杂性来自于FacebookUser与朋友的关系。对于行数的一半,对于一个关系,您可以使用一行,其中FacebookUser的ID可以位于任一外键列中。用户有朋友或朋友,因此您可以在FacebookFriend上有两个has_many :through
关联,每个关联在FacebookFriendRelationship中使用不同的外键。或者您可以在没有模型的情况下执行HABTM,并在每个关联中使用foreign_key和association_foreign_key选项。无论哪种方式,您都可以添加一个方法来将两个关联添加到一起(因为它们是数组)。相反,如果您不关心必须使用ActiveRecord以正常方式删除关联,则可以在单个has_many中使用自定义SQL。但是,根据您的意见,我认为您希望避免这种复杂性,我同意您的看法,除非您真的必须限制关系行数。但是,它不是将占用数据的连接表行的数量,它将是您保存在FacebookFriends表中的所有用户信息。