社交网站的好友表
Posted
技术标签:
【中文标题】社交网站的好友表【英文标题】:Friends table for a social networking site 【发布时间】:2012-08-13 17:46:25 【问题描述】:我一直在做一个社交网站。这里一个用户请求另一个用户成为他的朋友(朋友请求)。我想到了一个“朋友”表,看起来像
Table Name: Friends
Coloumns :
User1 - Int - FK
User2 - Int - FK
Request - Enum('0','1')
Time - DateTime
PK - (User1, User2)
在请求字段中,当用户 1 向用户 2 提出请求时,存储“0”,当用户 2 批准请求时,存储“1”。
当我想检索用户的所有朋友时,就会出现问题。我每次都必须检查请求字段是“0”还是“1”。还有其他方法吗?如果我有另一个存储 Friend 请求的所有详细信息的表会更好吗?
【问题讨论】:
为什么会出现这个问题?只要您将请求字段编入索引,就不应如此。像SELECT * FROM friends WHERE User1 = XX and Request = 1
这样的查询应该没问题。
@MikeBrant 如果 User1 是 User2 的朋友,那么 User2 也是 User1 的朋友。因此查询将变为SELECT * FROM friends WHERE (User1 = XX or User2 = XX ) and Request = 1
。会不会很复杂?
【参考方案1】:
在评论中,您基本上声明已建立的友谊(而不是请求)在您的设置中始终是对称的。在这种情况下,您基本上有两个选择:您可以将其存储在两行中,或者通过匹配任一列来选择它。前者将产生更简单的查询,但后者将确保对称性是数据库结构中固有的,并且还将避免存储重复数据。所以我会选择后者,即某种形式的WHERE (User1 = XX or User2 = XX )
。查询所花费的时间可能是仅查询一列所花费的时间的两倍在相同的行数上,但由于行数仅为其他存储方案的一半,因此净效应在性能方面应该可以忽略不计。
您是否需要单独的表来存储请求或已建立的友谊取决于这两者在关联数据和应用程序中的控制流方面的相似程度。因此,例如,如果您想向用户显示一个列表,该列表同时显示他已建立的友谊和他的未决请求,可能有不同的颜色或其他,但在同一个列表中,那么在数据库中拥有一个表会更多适当。另一方面,如果您主要将请求和友谊分开处理,那么拥有两张桌子会更自然。如果在某个时候,您决定友谊需要share_calendar
之类的属性,而请求需要confirmation_key
之类的属性,那么使用不同的表会更好。
如果您决定将其设为单个表,我建议对枚举使用更具描述性的值,例如调用列status
以及值requested
和established
。例如,我乍一看会将request = 1
的值解释为“这只是一个请求,而不是已建立的友谊”,这与您所联想的含义完全相反。当不同的人需要维护代码时,这种模糊性可能会导致错误。几年后,你将成为一个与现在不同的人,甚至你自己也可能会误解你的旧代码。所以要在那里描述。
还有一点需要注意:您可以始终使用视图来调整数据库在查询中的显示方式。例如,您可以创建一个视图
CREATE VIEW SymmetricEstablishedFriends AS
SELECT User1 AS Me, User2 AS Friend, Time
FROM Friends
WHERE Status = 'established'
UNION
SELECT User2 AS Me, User1 AS Friend, Time
FROM Friends
WHERE Status = 'established'
这会将数据仅限于已建立的友谊,并会为您处理对称的事情。在查询中使用此类视图,您可以避免在每个查询中处理表结构的所有细节。如果你改变了这些细节,改变的地方就会更少。
【讨论】:
谢谢。我想我得到了答案。【参考方案2】:我会将您的数据分成requests
和friendships
。当request
获得批准后,将其转换为friendship
。它们确实是两个不同的对象,应该这样对待。
Requests ::
requesting_user_id : int()
requested_user_id : int()
date_requested : datetime()
status_id : int()
Statuses ::
(Active, Declined, Accepted, Ignored)
Friendships ::
friendship_id : int()
user_id : int()
friend_id : int()
如果请求被拒绝,可能会删除它,或者为它设置一个列(以防止人们重复请求同一个用户的友谊)。您必须将请求转换为两个友谊(每个方向一个)以便于索引
SELECT friend_id FROM friendships WHERE user_id = ?
【讨论】:
所以我应该存储两个元组,如 user1, user2 和 user2, user1。对吗? 在friendships
?是的,这似乎有道理。
插入 2 行和删除 2 行似乎是一个漫长的过程。
可能是,但您可能会进行比插入/删除更多的查找以上是关于社交网站的好友表的主要内容,如果未能解决你的问题,请参考以下文章