Zac*_*tes 34 database-design social-networking
我正在尝试设计一个数据模型,表示一个用户是另一个用户的朋友.这是我到目前为止所提出的,但它似乎很笨重,有更好的解决方案吗?
User
=====
Id
Name
etc...
UserFriend
===========
UserId
FriendId
IsMutual
IsBlocked
Run Code Online (Sandbox Code Playgroud)
cha*_*aos 56
UserRelationship
====
RelatingUserID
RelatedUserID
Type[friend, block, etc]
Run Code Online (Sandbox Code Playgroud)
同意共同不属于专栏; 打破正常化.
Art*_*kov 37
要为每两个用户创建一条记录并避免消耗建议方法所建议的额外内存(因为每个用户有两条记录,所以需要两倍的内存),您可以执行以下操作:
表结构:
USER_RELATIONSHIP {
user_first_id,
user_second_id,
type
primary key(user_first_id, user_second_id)
}
Run Code Online (Sandbox Code Playgroud)确保: user_first_id < user_second_id
最有趣的部分 - type:对于关系的所有可能状态,您可以创建相应的值.例如:
pending_first_second
pending_second_first
friends
block_first_second
block_second_first
block_both
Run Code Online (Sandbox Code Playgroud)你有什么:
user_first_id < user_second_id确保了仅存在一个给定的两个用户之间的关系的记录,因为这和主键约束不会允许将其放置否则.要找出两个用户之间的关系(以及更新),您只需通过一个查询:
select * from USER_RELATIONSHIP where
user_first_id = user1_id and
user_second_id = user2_id;
Run Code Online (Sandbox Code Playgroud)
没有一个or声明会检查这个列反之亦然,这更快.
示例场景:
no record :没有关系
pending_first_second :第一个向第二个朋友提出请求
friends :第二个批准了朋友请求
no record :其中一个用户从他的朋友那里删除了另一个
此解决方案在内存和速度方面都很有效,因为您只创建,存储和更新一条记录.
我目前正在为客户建立一个社交网站,我这样表达了一些观点
CREATE TABLE [dbo].[PersonFriend] (
[Id] INT IDENTITY (1, 1) NOT NULL,
[Timestamp] DATETIME NOT NULL,
[ChangeUser] NVARCHAR (200) NOT NULL,
[FriendStatusId] TINYINT NOT NULL,
[Person1Id] INT NOT NULL,
[Person2Id] INT NOT NULL,
[Person1RequestTimestamp] DATETIME NOT NULL,
[Person2AcknowledgeTimestamp] DATETIME NULL
);
Run Code Online (Sandbox Code Playgroud)
每个人都存储在Person表中(想象一下).Person1Id和Person2Id字段是人员表的FK.我在FriendStatus表中保留了一个状态列表,用于覆盖是否已经请求,接受,拒绝,忽略等.Timestamp字段在我的设计中是标准的,用于表示记录创建(它是由基础持久化类使用的模式事物由于Person1RequestTimestamp包含相同的数据,因此它在此表中的重复类型.当Person2看到请求并在其上发出一个动作(在FriendStatusId中显示)并将其存储在Person2AcknowledgeTimestamp中时,我也会捕获.
这种设计的核心假设之一可以说是Person1要求Person2的友谊 - 如果这种友谊被接受,那么友谊被认为是相互的.