I'm trying to design a data model that denotes one user being the friend of another user. This is what i've come up with so far, but it seems clunky, is there a better solution?
User ===== Id Name etc... UserFriend =========== UserId FriendId IsMutual IsBlocked
Graph databases work by storing the relationships along with the data. Because related nodes are physically linked in the database, accessing those relationships is as immediate as accessing the data itself.
There are three types of relationships between the data you are likely to encounter at this stage in the design: one-to-one, one-to-many, and many-to-many. To be able to identify these relationships, you need to examine the data and have an understanding of what business rules apply to the data and tables.
A table relationship works by matching data in key fields — often a field with the same name in both tables. In most cases, these matching fields are the primary key from one table, which provides a unique identifier for each record, and a foreign key in the other table.
UserRelationship ==== RelatingUserID RelatedUserID Type[friend, block, etc]
Agree that mutuality doesn't belong as a column; breaks normalization.
To go one record per two users and avoid consuming extra memory that the proposed methods suggest (twice as much as needed, since there are two records for each user), you can do the following:
Table structure:
USER_RELATIONSHIP { user_first_id, user_second_id, type primary key(user_first_id, user_second_id) }
Ensure: user_first_id < user_second_id
The most interesting part - type
: for all of the possible states of a relationship, you create the corresponding values. For exmaple:
pending_first_second pending_second_first friends block_first_second block_second_first block_both
What you have:
user_first_id < user_second_id
ensures that there is only one record of a relationship between two given users, since this and primary key constraints won't allow placing it otherwise.To find out the relationship between two users (as well as update), you simply go by a single query:
select * from USER_RELATIONSHIP where user_first_id = user1_id and user_second_id = user2_id;
without an or
statement that would check this columns vice versa, which is faster.
Example scenario:
no record
: are not in a relationship
pending_first_second
: the first made a friend request to the second
friends
: the second approved the friend request
no record
: one of the users removed the other from his firends
This solution is efficient in terms of both memory and speed, because you create, store and update only one single record.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With