I am implementing “Add Friend” in my web app, so users could add other users as fiends.
We have 2 tables: tbl_users and tbl_relations, tbl_users have an unique ID for the registered users and tbl_relations will store the users which are friends, for example some rows in tbl_relations are:
id user_id_1 user_id_2
1 4 6
2 4 8
3 8 23
4 12 84
5 3 4
...
In the above results, the id is the unique id for the tbl_relations, user_id_1 is foreign key to tbl_users and user_id_2 is foreign key to tbl_users, now imagine we want to query and check if user with id “4” is friend with user with id “9” or not, here we need to send the query in 2 ways, I mean:
SELECT * FROM tbl_relations WHERE (user_id_1 = '4' AND user_id_2 = '9') OR (user_id_1 = '9' AND user_id_2 = '4')
The above query seems a little weird to me, there should be another way for implementing this I guess, maybe a different database structure?
Or another query, we want to get the mutual friends between users with id “4” and “8”, how I’m supposed to get the mutual friends in this scenario? is there any better database structure for this?
I would appreciate any kind of help.
I would de-normalize the relation such that it’s symmetric. That is, if 1 and 2 are friends, i’d have two rows (1,2) and (2,1).
The disadvantage is that it’s twice the size, and you have to do 2 writes when forming and breaking friendships. The advantage is all your read queries are simpler. This is probably a good trade-off because most of the time you are reading instead of writing.
This has the added advantage that if you eventually outgrow one database and decide to do user-sharding, you don’t have to traverse every other db shard to find out who a person’s friends are.