我正在尝试设计一个数据模型,表示一个用户是另一个用户的朋友.这是我到目前为止所提出的,但它似乎很笨重,有更好的解决方案吗?
User ===== Id Name etc... UserFriend =========== UserId FriendId IsMutual IsBlocked
chaos.. 56
UserRelationship ==== RelatingUserID RelatedUserID Type[friend, block, etc]
同意共同不属于专栏; 打破正常化.
UserRelationship ==== RelatingUserID RelatedUserID Type[friend, block, etc]
同意共同不属于专栏; 打破正常化.
要为每两个用户创建一条记录并避免消耗建议方法所建议的额外内存(因为每个用户有两条记录,所以需要两倍的内存),您可以执行以下操作:
表结构:
USER_RELATIONSHIP { user_first_id, user_second_id, type primary key(user_first_id, user_second_id) }
确保: user_first_id < user_second_id
最有趣的部分 - type
:对于关系的所有可能状态,您可以创建相应的值.例如:
pending_first_second pending_second_first friends block_first_second block_second_first block_both
你有什么:
在user_first_id < user_second_id
确保了仅存在一个给定的两个用户之间的关系的记录,因为这和主键约束不会允许将其放置否则.
通过在关系状态之间进行适当切换,可以确定两个用户中的每个用户之间的关系.如果两个用户之间没有关系,则没有记录.
要找出两个用户之间的关系(以及更新),您只需通过一个查询:
select * from USER_RELATIONSHIP where user_first_id = user1_id and user_second_id = user2_id;
没有一个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 );
每个人都存储在Person表中(想象一下).Person1Id和Person2Id字段是人员表的FK.我在FriendStatus表中保留了一个状态列表,用于覆盖是否已经请求,接受,拒绝,忽略等.Timestamp字段在我的设计中是标准的,用于表示记录创建(它是由基础持久化类使用的模式事物由于Person1RequestTimestamp包含相同的数据,因此它在此表中的重复类型.当Person2看到请求并在其上发出一个动作(在FriendStatusId中显示)并将其存储在Person2AcknowledgeTimestamp中时,我也会捕获.
这种设计的核心假设之一可以说是Person1要求Person2的友谊 - 如果这种友谊被接受,那么友谊被认为是相互的.
我会做类似于你所拥有的东西,但删除"IsMutual"标志.当它是相互的时,只需添加具有反向值的第二行.它确实添加了行,但感觉更清洁.