我正在尝试设计一个数据模型,表示一个用户是另一个用户的朋友。这是我到目前为止所提出的,但看起来很笨重,是否有更好的解决方案?
User
=====
Id
Name
etc...
UserFriend
===========
UserId
FriendId
IsMutual
IsBlocked
答案 0 :(得分:53)
UserRelationship
====
RelatingUserID
RelatedUserID
Type[friend, block, etc]
同意共同不属于专栏;打破正常化。
答案 1 :(得分:29)
要每两个用户一个记录,并避免消耗建议方法建议的额外内存(需要两倍,因为每个用户有两条记录),您可以执行以下操作:
表格结构:
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
:其中一位用户将其他用户从他的朋友中删除
此解决方案在内存和速度方面都很有效,因为您只创建,存储和更新一条记录。
答案 2 :(得分:8)
我目前正在为客户建立一个社交网站,我用这种方式表达了
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表中保留了一个状态列表,用于覆盖是否已经请求,接受,拒绝,忽略等。时间戳字段在我的设计中是标准的,用于表示记录创建(它是基本持久化类使用的模式事物)由于Person1RequestTimestamp包含相同的数据,因此它在此表中的重复类型。当Person2看到请求并在其上发出一个动作(在FriendStatusId中显示)并将其存储在Person2AcknowledgeTimestamp中时,我也会捕获。
这种设计的核心假设之一可以说是Person1要求Person2的友谊 - 如果这种友谊被接受,那么友谊被认为是相互的。
答案 3 :(得分:5)
我会做类似于你所拥有的东西,但删除“IsMutual”标志。当它是相互的时,只需添加具有反向值的第二行。它确实添加了行,但感觉更清洁。
答案 4 :(得分:2)
也许添加一个Relationship表,将关系属性放在那里,然后从UserFriend引用它。
答案 5 :(得分:2)
可能在顶部,但可以使用语义网来模拟这个。可以使用FOAF(FOAF朋友的朋友)格式。
答案 6 :(得分:2)
您如何看待我的解决方案?
你有3张桌子
1 **the user** (id,.etc)
2 **friend_request**(id,flaggerID,flaggedID)
3 **friend**(id,frienderID,friendedID)
你登录,检查我是否在朋友表中,如果是列出朋友(我在friender&gt; list friended)(我在friended&gt; listfriender)
我有要求吗? (我在flaggedID吗?)认识他?如果没有,删除记录;如果是,请在请求中创建新记录,因为我在旗手中被推入并且旗手被标记。现在我们在请求表中有2个记录之间的相互关系,所以我们删除它们并将它们放在朋友表中。 易于分离req / friends。
答案 7 :(得分:2)
我是这样做的:
TABLE用户
id name
-----------
1 foo
2 roo
3 shoo
4 mooo
表朋友关系
id u_id f_id
--------------
1 1 2
2 2 1
3 3 1
4 1 3
每次朋友请求都接受插入反向方式1 2 & 2 1
和简单查询:
$ufq=mysql_query("SELECT t1.f_id,t2.id,t2.name FROM friends AS t1, user AS t2 WHERE t1.u_id='$u_id' AND t2.id=t1.f_id ORDER BY t2.name ")or die(mysql_error());
while($fn=mysql_fetch_array($ufq)){
echo $fn["name"].'<br>';
}
答案 8 :(得分:1)
与传统的雇主/老板和用户/配偶自我加入方案相比,友谊不那么明确。友谊是一种关系还是一种活动?由于忽视了后者,我收到了相当多的批评。无论哪种方式,无论数据模型的通用程度如何,您可能都需要多个表。
答案 9 :(得分:1)
你真的需要一张物理桌来发现是否有共同的朋友?为什么不进行如下的SQL查询:
SELECT U.ID, U.NAME FROM USER U
INNER JOIN USERFRIEND UF
ON U.ID = UF.FRIENDID
WHERE U.ID = (SELECT USER.ID FROM USER
WHERE USER.ID = friend_id AND USER.ID != your_id);
查询的结果应该返回所有共同的朋友。
答案 10 :(得分:0)
我认为你应该创建两个表:
用户
u_id int
u_username字符串
balahhh ............
2.友谊
fs_id int
related_id int
related_id int
答案 11 :(得分:0)
好吧,我已经迟到了,但这是我的出价。
首先是表格:
User
-id
Type
-id
Relationship
-user_id_1
-user_id_2
-type_id
现在,我想保持我的类型表简单。因此,我添加的类型仅代表单个用户与另一个用户的关系。它们永远不代表双向关系。例如:
friend
ignored
这使得添加新类型变得容易。我不必考虑或创建所有类型的所有可能组合。我只是添加新类型。
要设置友谊,您需要在关系表中输入2个条目。如果两个用户都认为他们是朋友,那么他们就是朋友。如果只有一个人说他是另一个人的朋友,而另一个人阻止他,那么他们就不是朋友。
进行查询非常简单。以下是您如何获得MySQL中的所有朋友:
SELECT u.* FROM user u
LEFT JOIN relationship r1 ON u.id = r1.user_id_2
LEFT JOIN relationship r2 ON u.id = r2.user_id_1
WHERE r1.user_id_1 = <my_user_id> # my relationship with them
AND r1.type_id = <friend_type_id> # i say i'm a friend
AND r2.user_id_2 = <my_user_id> # their relationship with me
AND r2.type_id = <friend_type_id> # they say they're friends
我也认为这种方法更加安全,交易安全&#34;。想象一下,您向某人发送了一个朋友请求,然后阻止该人。如果那个人以后接受了朋友请求,那就不重要了。它并没有改变关系的状态,因为它们是完全独立的。
如果你有一个代表双向关系的单一类型,你将被迫在你的代码中进行某种评估,一旦朋友接受了朋友的请求,关系的新状态究竟应该是什么。如果您不这样做,您最终可能会取消阻止用户并让该用户与他或她已阻止的用户成为朋友。
我宁愿在数据库级别处理这个问题。如果你有一群程序员正在处理这个应用程序,那么在某人忘记这个问题并且创建了一个难以发现的bug之前,它不会花很长时间。
答案 12 :(得分:0)
根据我的理解,友谊是两个用户(User1和User2)之间的关系的结果,并且由于user1可以将0个或多个用户作为朋友,反之亦然,因此user2是连接表中间的“朋友”来表示这种关系:
User1 id(int)用户名(string)
User2 id(int)用户名(string)
朋友 ---- id(int)user1_Id(int)user2_Id(int)活动(布尔)
user1_Id和user2_Id都是Frind表中的FK
我希望我是对的。
答案 13 :(得分:-1)
我还在做一个类似的项目,您需要描述友谊, 其中有关您自己和朋友的信息是从一张桌子上获得的。 。
答案: 我创建了“友谊”表,在该表中,我通过“ friend_id”获取了朋友的数据以及他们见面的那天。为了链接它们,我使用了“关系”表。通过此链接Friend relation
生成的ERD图(数据库)的图像