我正在Rails的一个社交网站上工作,目前我可以想到几种实现友谊的方式(就像Facebook)。但是,由于许多应用程序的功能将取决于应用程序的这一部分,因此我对提交一个文件感到有些担忧,然后意识到自己可以做得更好,然后进行迁移并更改整个一件事一件事。

如果你们可以建议哪一种是最好的方法,那将是很棒的。另外,如果我的架构都不够好,请随时提出一个新的架构

建筑1

一张包含3列的用于友谊的表格-

  • user_id(发送请求的用户的ID)
  • friend_id(接收请求的用户的标识)
  • 待处理( bool(boolean) 值,处于保留状态。如果请求被接受,则为False,否则为true)

    得到用户的所有 friend
      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。
  • DRY代码。接受 friend 的请求只需要查找记录并仅更新一个字段( bool(boolean) 值-待处理)。取消联系只需找到记录并删除它就可以了。

  • 我能想到的缺点-
  • User.friends和User.friend_requests不能立即加载,因为它们实际上不是ActiveRecord关联。从长远来看,这可能是一个主要的放慢点,尤其是在搜索功能中,我希望按多个共同的 friend 对结果进行排名。

  • 建筑2

    两张桌子。一个用于友谊,另一个用于 friend 的请求-
    友谊会像-
  • user_id(友谊中的用户之一)
  • friend_id(友谊中其他用户的ID)

  • Friend Requests表也将像-
  • user_id(友谊中的用户之一)
  • friend_id(友谊中其他用户的ID)

  • 要获得用户的所有 friend -
    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很容易加载。这可以提高许多地方的性能,在这些地方我希望在单个查询中加载一群用户的 friend ,而不是一遍又一遍地访问数据库并执行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)

    最佳答案

    我会推荐第二种模型,即friend_requestfriendship的单独表。尽管这些表当前可能保存完全相同的数据,但随着时间的推移,我希望它们会有所不同。

    以下是一些可能发生这种情况的方式:-

  • 您想允许他们与好友请求一起发送消息(“嘿,从学校记住我”)
  • 您决定要保留有关好友请求的统计信息,例如何时发出请求
  • 您决定要在数据库中保留拒绝的 friend 请求(一旦拒绝则禁止进一步的请求)

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

    您是否应该在表格中放置两行,分别代表关系的两个方向?这是归一化与性能的问题。

    归一化的答案是仅包括一行。该模型:
  • 更易于获取更新/插入/删除,因为只有一排可担心
  • 更加难以查询,因为您将需要从两个方向进行查询

  • 归一化的答案(因为存储了重复的数据)将包括两行:此模型:
  • 很难更新/插入/删除,因为有两行可以保持同步
  • 可以更快地查询,因为您可以从一个方向查询
  • 09-19 05:47