社交网络应用程序中友谊的最佳数据库架构

时间:2015-09-13 20:05:51

标签: sql ruby-on-rails database activerecord architecture

我正在Rails的社交网站上工作,目前我可以想到几种可以实现友谊的方式(就像Facebook一样)。但是由于很多应用程序的功能将取决于应用程序的这一部分,我有点担心提交到一个,然后意识到我可以做得更好,然后进行迁移并改变整个事情一个接一个。

如果你们可以建议哪种方式最好,那就太好了。此外,如果我的架构都不够好,请随意建议一个新架构

建筑1

包含3列友谊的单个表 -

  • user_id(发送请求的用户的ID)
  • friend_id(收到请求的用户的ID)
  • pending(布尔值保持状态。如果请求被接受,则返回false,否则返回true)

获取用户的所有朋友

  def friends
    user_ids = Friendship.where(
      '(user_id = :id OR friend_id = :id) AND pending = false',
       id: self.id
    ).pluck(:user_id, :friend_id)
     .flatten
     .uniq
     .reject { |id| id == self.id }

    users = User.where(id: user_ids)
  end

获取用户收到的所有好友请求 -

def friend_requests
  friend_ids = Friendship.where('friend_id = ? AND pending = true', self.id).all
  users = User.where(id: friend_ids)
end

我能想到的优点 -

  • 与其他体系结构相比,它在数据库中需要的表和记录数量最少。我不确定这是否真的有优势,因为我听说表中的记录数不会影响性能。如果我错了,请纠正我。
  • 只需要几次验证。首先,user_id在friend_id的范围内是唯一的。其次,user_id不等于friend_id。
  • 干密码。接受朋友请求只需要查找记录并只更新一个字段(布尔值 - 待定)。非友好需要只是找到记录并删除它

我能想到的缺点 -

  • User.friends和User.friend_requests不是急于加载的,因为它们实际上不是ActiveRecord关联。从长远来看,这可能是一个主要的减速点,尤其是搜索功能,我希望通过一些共同的朋友对结果进行排名。

建筑2

两张桌子。一个用于友谊,一个用于朋友请求 - 友谊就像 -

  • user_id(友谊中某个用户的ID)
  • friend_id(友谊中其他用户的ID)

朋友请求表也会像 -

  • user_id(友谊中某个用户的ID)
  • friend_id(友谊中其他用户的ID)

获取用户的所有朋友 -

has_many :friendships,
  class_name: "Friendship",
  foreign_key: :user_id,
  primary_key: :id

has_many :friends,
  through: :friendships,
  source: :friend

获取用户的所有好友请求 -

has_many :friend_requests,
  class_name: "FriendRequest",
  foreign_key: :friend_id,
  primary_key: :id

我能想到的优点是 -

  • User.friends和User.friend_requests是可加载的。这可以提高很多地方的性能,我会在一个查询中急切地加载一堆用户的朋友,而不是一遍又一遍地访问数据库并做User.friends

我能想到的缺点是 -

  • 重复友谊条目。为了使User.friends关联工作,我将不得不为一个friendhsip创建2个条目。
| id  | user_id | friend_id |  
-----------------------------
|  1  |   15    |    30     |
-----------------------------
|  2  |   30    |    15     |
-----------------------------
  • 这将需要复杂的验证,例如:如果第1行是有效的,则验证第2行的存在(在上面的示例中)。还有很多其他人
  • 建立友谊会很复杂。它需要
    • 从朋友请求表中删除条目
    • 在friends表中创建2行
    • 我知道这听起来不是一个真正的劣势,但对我来说,创建/删除3个相互依赖的条目似乎有很多错误

我想最后问题归结为 -

数据库(架构1)中较少数量(一半)的条目与更多条目(架构2)相比具有显着优势吗?

单个友谊有2个条目有多糟糕? (建筑2)

1 个答案:

答案 0 :(得分:3)

我会推荐第二个模型,friend_requestfriendship的单独表格。虽然这些表目前可能保存完全相同的数据,但随着时间的推移,我预计它们会分歧。

以下是可能发生的一些方法: -

  • 你想让他们和朋友的请求一起发送信息(“嘿,记住我从学校开始”)
  • 您决定要保留有关好友请求的统计信息,例如请求发布时
  • 您决定要在数据库中保留已拒绝的好友请求(拒绝进一步拒绝请求)

因为它们是不同的东西,所以应该创建不同的表而不是重载单个表。创建表格并不困难。

你应该在表格中放两行,代表两种关系的方向吗?这是规范化性能的问题。

规范化答案只包含一行。这个模型:

  • 更容易获得更新/插入/删除,因为只需要担心一行
  • 查询更困难,速度更慢,因为您需要从两个方向进行查询

反规范化答案(因为存储了重复数据)是包括两行:此模型:

  • 更难/更新/插入/删除,因为有两行要保持同步
  • 查询速度更快,因为您可以从一个方向查询