是否有一种优雅的方式来存储双重关系(即用户1和用户2是朋友)

时间:2012-01-10 19:06:08

标签: database database-design social-networking bit-manipulation bitmask

本月我在两个不同的工作中遇到了同样的问题:

Version 1: User 1 & User 2 are friends
Version 2: Axis 1 & Axis 2 when graphed should have the quadrants colored...

问题是,我没有看到使用RDBMS存储和查询此信息的优雅方式。

有两种明显的方法:

方法1:

store the information twice (i.e. two db rows rows per relationship):
u1, u2, true 
u2, u1, true
u..n, u..i, true
u..i, u..n, true

have rules to always look for the inverse on updates: 
on read, no management needed
on create, create inverse
on delete, delete inverse
on update, update inverse

Advantage:    management logic is always the same.
Disadvantage: possibility of race conditions, extra storage (which is admittedly cheap, but feels wrong)

方法2:

store the information once (i.e. one db row per relationship)
u1, u2, true
u..n, u..i, true

have rules to check for corollaries:
on read, if u1, u2 fails, check for u2, u1 
on create u1, u2: check for u2, u1, if it doesn't exist, create u1, u2
on delete, no management needed
on update, optionally redo same check as create

Advantage: Only store once
Disadvantage: Management requires different set of cleanup depending on the operation

我想知道是否有第三种方法沿着“使用f(x,y)的关键线,其中f(x,y)对于每个x,y组合都是唯一的,其中f(x,y) === f(y,x)“

我的直觉告诉我应该有一些可以满足这些要求的按位运算组合。类似于两列的东西:

key1 = x&& ÿ key2 = x + y

我希望那些花更多时间在数学系的人,而且在社会学系的时间更少的人已经看到了这种可能性或不可能性的证据,并且可以提供一个快速的“[你好白痴],它很容易被证实(im)可能,请看这个链接“(名字叫可选)

任何其他优雅的方法也会非常受欢迎。

由于

5 个答案:

答案 0 :(得分:7)

还有一种方法可以通过添加额外约束来使用第二种方法。检查u1 < u2

CREATE TABLE User
( Name VARCHAR(10) NOT NULL
, PRIMARY KEY (Name)
) ;

CREATE TABLE MutualFriendship
( u1 VARCHAR(10) NOT NULL
, u2 VARCHAR(10) NOT NULL
, PRIMARY KEY (u1, u2)
, FOREIGN KEY (u1) 
    REFERENCES User(Name)
, FOREIGN KEY (u2) 
    REFERENCES User(Name)
, CHECK (u1 < u2) 
) ;

要阅读,创建,插入或更新的规则必须使用(LEAST(u1,u2), GREATEST(u1,u2))

答案 1 :(得分:2)

在SQL中,很容易实现约束来支持您的第一种方法:

CREATE TABLE MutualFriendship
(u1 VARCHAR(10) NOT NULL,
 u2 VARCHAR(10) NOT NULL,
 PRIMARY KEY (u1,u2),
 FOREIGN KEY (u2,u1) REFERENCES MutualFriendship (u1,u2));

INSERT INTO MutualFriendship VALUES
('Alice','Bob'),
('Bob','Alice');

答案 2 :(得分:1)

对于任何有兴趣的人,我玩了一些按位操作,发现以下内容似乎符合f(x,y)的标准:

#Python, returns 3 tuple
def get_hash(x, y):
  return (x & y, x | y, x * y)
但是,我无法证明这一点。

答案 3 :(得分:0)

“x是y的朋友。”

定义(x,y)对的表并强制执行规范形式,例如: X&LT; Y。这将确保您不能在数据库中同时拥有(p,q)和(q,p),因此它将确保“存储一次”。

创建一个视图为SELECT x,y FROM FRIENDS UNION SELECT x为y,y为x FROM FRIENDS。

针对基表进行更新(缺点:更新者必须知道强制规范表单),针对视图进行查询。

答案 4 :(得分:-2)

你似乎把朋友的数量限制为1.如果是这种情况,那么我会使用类似的东西 U1,U2 U2,U1 U3,空 U4,U5 U5,U4

u3没有朋友。