Database design 数据库设计:捕捉用户/朋友关系的最佳表结构?

Database design 数据库设计:捕捉用户/朋友关系的最佳表结构?,database-design,social-networking,Database Design,Social Networking,我试图设计一个数据模型,表示一个用户是另一个用户的朋友。这是我到目前为止提出的,但它似乎很笨重,有更好的解决方案吗 User ===== Id Name etc... UserFriend =========== UserId FriendId IsMutual IsBlocked 也许可以添加一个关系表,将关系属性放在那里,并从UserFriend引用它。我会做一些类似于您所做的事情,但删除“IsMutual”标志。当第二行是相互的时,只需添加第二行,并使用反向值即可。它确实添加了行,但感

我试图设计一个数据模型,表示一个用户是另一个用户的朋友。这是我到目前为止提出的,但它似乎很笨重,有更好的解决方案吗

User
=====
Id
Name
etc...

UserFriend
===========
UserId
FriendId
IsMutual
IsBlocked

也许可以添加一个关系表,将关系属性放在那里,并从UserFriend引用它。

我会做一些类似于您所做的事情,但删除“IsMutual”标志。当第二行是相互的时,只需添加第二行,并使用反向值即可。它确实添加了行,但感觉更干净

UserRelationship
====
RelatingUserID
RelatedUserID
Type[friend, block, etc]

同意相互性不属于一列;中断正常化。

友谊没有经典的雇主/老板和用户/配偶自加入场景那么清晰。友谊是一种关系还是一种活动?我因忽视后者而受到相当多的批评。无论采用哪种方式,您都可能需要不止一个表,无论您的数据模型多么通用。

可能过于简单,但可以使用语义网对此进行建模。可以使用FOAF(FOAF朋友的朋友)格式

我目前正在为一个客户建立一个社交网站,我是这样表达的

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字段在person表中是FK。我在FriendStatus表中保留了一个状态列表,用于覆盖某些内容是否已被请求、接受、拒绝、忽略等。时间戳字段在我的设计中是标准的,用于指示记录创建(它是基本持久性类使用的模式)它在这个表中是重复的,因为Person1RequestTimestamp包含相同的数据。我还捕获Person2看到请求并对其执行操作(在FriendStatusId中指示)的时间,并将其存储在Person2AcknowledgeTimestamp中


这种设计的一个核心假设是,人1请求人2的友谊-如果友谊被接受,那么友谊被认为是相互的。

你真的需要一个物理表来发现是否有共同的朋友吗?为什么不执行如下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);

查询结果应返回所有共同的好友。

您认为我的解决方案如何

User
=====
Id
Name
etc...

UserFriend
===========
UserId
FriendId
IsMutual
IsBlocked
你有三张桌子

1 **the user** (id,.etc)
2 **friend_request**(id,flaggerID,flaggedID)
3 **friend**(id,frienderID,friendedID)
您登录,检查我是否在朋友表中,如果是,请列出朋友(我在friender>list friended中)(我在friended>listfriender中)

我有什么要求吗?(我在Flaggedod?)认识他吗?如果没有,删除记录;如果是,请在请求中创建新记录,因为我被放入了标记器,并且标记器被标记。现在,我们在请求表中的两条记录之间有了相互关系,所以我们删除了这两条记录并将它们放在朋友表中。 很容易分开请求/朋友。

我是这样做的:

表用户

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
每次接受好友请求时,以反向方式插入
12&21
和简单查询:

$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>';
}
$ufq=mysql\u query(“从朋友处选择t1.f\u id、t2.id、t2.name作为t1,用户作为t2,其中t1.u\u id='$u\u id'和t2.id=t1.f\u id按t2.name排序”)或die(mysql\u error());
而($fn=mysql\u fetch\u数组($ufq)){
回声$fn[“名称”]。
; }
我认为您应该创建两个表:

1.用户
u_id int
u_用户名字符串
巴拉赫………

2.友谊
fs_id int
关联id int
相关id int

要使每两个用户有一条记录,并避免使用建议方法建议的额外内存(两倍于所需的内存,因为每个用户有两条记录),可以执行以下操作:

  • 表结构:

    USER_RELATIONSHIP {
        user_first_id,
        user_second_id,
        type
    
        primary key(user_first_id, user_second_id)
    }
    
  • 确保:
    user\u first\u id

  • 最有趣的部分-
    类型
    :对于关系的所有可能状态,创建相应的值。对于exmaple:

    pending_first_second
    pending_second_first
    friends
    block_first_second
    block_second_first
    block_both
    
  • 你所拥有的:

  • user\u first\u id
    确保只有一个 记录两个给定用户之间的关系,因为这与主键约束有关 不允许将其放置在其他位置
  • 通过在关系状态之间进行适当的切换,可以确定两个用户之间的关系。如果两个用户之间没有关系,则没有记录
  • 要找出两个用户之间的关系(以及更新),只需执行一个查询:

    select * from USER_RELATIONSHIP where
        user_first_id = user1_id and
        user_second_id = user2_id;
    
    没有检查此列的
    语句,反之亦然,这会更快

  • 示例场景

  • 无记录
    :不在关系中

  • pending_first_second
    :第一个向第二个发出好友请求

  • 朋友
    :第二个批准了朋友请求

  • 无记录
    :其中一个用户从他的朋友中删除了另一个


  • 这个解决方案在内存和速度方面都很有效,因为您只创建、存储和更新一条记录。

    好吧,我来晚了,但这是我的出价

    首先是表格:

    User
    -id
    
    Type
    -id
    
    Relationship
    -user_id_1
    -user_id_2
    -type_id
    
    现在,我想保持我的类型表简单。因此,我添加的类型只表示单个用户与另一个用户的关系。它们从不代表双向关系。例如:

    friend
    ignored
    
    这使得添加新类型变得容易。我不必考虑或创造我所有类型的所有可能组合。我只是添加了新类型

    要建立友谊,需要在关系表中输入两个条目。如果两个用户都同意他们是朋友,那么他们就是朋友。如果只有一个人说他是另一个人的朋友,而另一个人阻止了他,那么他们就不是朋友

    进行查询非常简单。以下是您在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
    
    从用户u中选择u.*
    u.id上的左连接关系r1=r1.user\u id\u 2
    u.id=r2.user\u id\u 1上的左连接关系r2
    其中r1.user_id_1=#我与t的关系