I have a question concerning the performance of 2 different options, which one is better?
Explanation: I have 5 tables in a postgresql db: users, followers, posts, likes and comments. They look like this (simplified):
users (
user_id bigint,
username character varying(24)
);
followers (
follower_id bigint,
user_id bigint,
following_user_id bigint,
timestamp timestamp with time zone DEFAULT NOW()
);
post (
post_id bigint,
user_id bigint,
text text,
timestamp timestamp with time zone DEFAULT NOW()
);
likes (
like_id bigint,
post_id bigint,
user_id bigint,
timestamp timestamp with time zone DEFAULT NOW()
);
comments (
comment_id bigint,
post_id bigint,
user_id bigint,
comment text,
timestamp timestamp with time zone DEFAULT NOW()
);
I now want to make a notifications component in my app to show someone he received a new like or comment on a post.
FIRST OPTION:
The first option (I have now) is to create a sixth table named notifications:
notifications (
notification_id bigint,
type character varying(12),
g_user_id bigint,
r_user_id bigint,
s_user_id bigint,
post_id bigint,
timestamp timestamp with time zone DEFAULT NOW()
);
A notification row would look like this:
+---------------------------------------------------------------------------------------+
| notification_id | type | g_user_id | r_user_id | s_user_id | post_id | timestamp |
+---------------------------------------------------------------------------------------+
| 1 | post | 1 | NULL | NUL | 1 | 2021-01-01...|
| 2 | comm | NULL | 2 | 1 | 1 | 2021-01-01...|
| 3 | like | NULL | 1 | 2 | 1 | 2021-01-01...|
| ... |
+---------------------------------------------------------------------------------------+
It seems to me this is the easiest solution, a query to select and order the notifications for a user (and fetch meta-data like the username of the sender_user_id) is easy with a JOIN.
The problem I'm facing is: I have more notification types (not only likes and comments but around 20 different notification types). Some notifications are for a user specific (defined in receiving_user_id), some notifications are 'general' and are for all users following an account (I defince this in general_user_id).
My (simplified) query to fetch these notifications now look like this. I'm selecting all notifications for r_user_id (receiving_user_id) 1 with a JOIN to the table users to select all usernames from the sending_user_ids (s_user_id) (if not null) and to select all "general" notifications (all notifications with g_user_id NOT NULL where g_user_id is a user_id that user_id = 1 is following in the table followers).
SELECT
a.notification_id,
a.type,
a.timestamp,
b.username
FROM
notifications a
LEFT JOIN
users b
ON
a.s_user_id = b.user_id
WHERE
(
a.r_user_id = 1
OR
a.g_user_id IN (SELECT following_user_id FROM followers WHERE user_id = 1)
)
ORDER BY
a.timestamp DESC
The biggest problem I have with this solution is that it requires an extra table and extra commands in my node.JS code. When someone likes a post, I have to create a notification row, when some dislikes a post, I have to delete this notification again.
SECOND OPTION:
My second option is to just leave these 5 tables and with a UNION ALL query "create" the notifications on the fly, if possible.
I don't know how other people create a notification system, and I didn't found much tutorials about it. Is it OK to create a separate notifications table (and use postgresql trigger functions to automatically create/delete notification rows), or should I create these notifications 'on the fly' based on the rows in likes, comments and posts?