views:

180

answers:

1

I'm trying to decide on the best way to model a relationship of records in a relational database. It's the classic friend/follow model:

~~~~

A User can have zero to many friends.
A User can have zero to many followers.

Friends and followers are both Users themselves.

~~~~~

What's the best way to model this?

Thanks!

+5  A: 

Users (UserId, ...)
Subscription (Subscriber, Publisher)
Friendship (FirstUser, SecondUser)

CREATE TABLE Users (
    UserID int not null primary key,
    ...
)

CREATE TABLE Subscription (
    Subscriber int not null references Users(UserID),
    Publisher int not null references Users(UserID),
    constraint ck_NotEqual check (Subscriber <> Publisher)
)

CREATE TABLE Friendship (
    FirstUser int not null references Users(UserID), 
    SecondUser int not null references Users(UserID),
    constraint ck_Order check (FirstUser < SecondUser) -- since friendship is reflective
)
Mehrdad Afshari
Since if A is friend B, B is also a friend of A. We could either record both relations or we could retain just one. With this check constraint, we enforce that the ID of first user is always less than the ID of the second so we could always know how to check for friendship and there won't be dupes.
Mehrdad Afshari
And a 'would-be friend' where there isn't the reciprocation is a 'follower' under this definition? Otherwise, I'd probably keep the Friendship table asymmetric: one entry would record that UserA regards UserB as a friend, and a separate entry would record that UserB regards UserA as a friend.
Jonathan Leffler
@Jonathan: I agree you need to be able to store a "friend invitation" that hasn't been accepted yet. Perhaps another table `Invitations` that is directional, includes the date of the invite (in case it needs to expire), etc. Once the recipient accepts, it moves to the `Friendship` table.
Bill Karwin
There are advantages to two rows per friendship solution, but having worked in a similar social networking project, IMO this way of handling the situation is much less problematic.
Mehrdad Afshari
I note you can't follow yourself, which is something Twitter, for example, effectively enforces. I can see why you might not want to deal with that in the database however.
deworde