views:

174

answers:

3

What is the best way to store user relationships, e.g. friendships, that must be bidirectional (you're my friend, thus I'm your friend) in a rel. database, e.g. MYSql?

I can think of two ways:

  1. Everytime a user friends another user, I'd add two rows to a database, row A consisting of the user id of the innitiating user followed by the UID of the accepting user in the next column. Row B would be the reverse.
  2. You'd only add one row, UID(initiating user) followed by UID(accepting user); and then just search through both columns when trying to figure out whether user 1 is a friend of user 2.

Surely there is something better?

+2  A: 

Using double rows, while it creates extra data, will greatly simplify your queries and allow you to index smartly. I also remember seeing info on Twitter's custom MySQL solution wherein they used an additional field (friend #, basically) to do automatic limiting and paging. It seems pretty smooth: http://engineering.twitter.com/2010/05/introducing-flockdb.html

Joseph Mastey
+3  A: 

I would have a link table for friends, or whatever, with 2 columns both being PK's, and both being FK's to the User table.

Both columns would be the UID, and you would have two rows per friend relationship (A,B and B,A). As long as both columns are PK's, it should still be in normal format (although others are free to correct me on this)

Its a little more complex of a query, but nothing that can't be abstracted away by a stored procedure or some business logic, and its in Normal Format, which is usually nice to have.

Lerxst
Just remember that in MySQL the default engine MyISAM does not support foreign keys, switch to InnoDB.
Geek Num 88
True enough, but if you absolutely had to use MyISAM, you could get away with these not being actual FK's, but it could affect your data integrity and normalization, stick with InnoDB
Lerxst
I would go with this system as well as it greatly simplifies the select queries for looking up friends, especially when you need to join against this table. However you should use transactions and stored procedures to make sure both rows are always inserted and deleted together (you do **not** want to accidentally delete one of the two rows).
too much php
A: 

Use a key value store, such as Cassandra for example.

ANON