lundi 27 juin 2016

How to implement @mention relation in the DBMS schema of a twitter-like website

I'm making a twitter-like website, using MySQL as database.

One User has many Microposts, and one Micropost has many Replies. The schema seems good until I introduce the mention relation.

When the website notifies someone that he has been @mentioned, the source text will also be displayed. The @mention can occurs both in Micropost content and Reply content, and I want to get both types of @mention source text in one query.

But I'm not sure how the Mention table schema should be designed. Here are some ideas I have thought, which one should be the best? Any better ideas?

Solution1

user_id      FOREIGN KEY users(user_id) 'the user mentioned
mention_type ENUM 1 - post, 2 - reply
post_id      FOREIGN KEY posts(post_id)
reply_id     FOREIGN KEY replies(reply_id)

In each row, either post_id, or reply_id will be NULL.

Query:

SELECT IF(mention_type = 1, post_text, reply_text) AS text,
       IF(mention_type = 1, 'Post', 'Reply') AS type
FROM mentions
INNER JOIN posts ON posts.post_id = post_id
INNER JOIN replies ON replies.reply_id = reply_id
WHERE mentions.user_id = @user_id

Solution2

user_id      FOREIGN KEY users(user_id)
mention_type ENUM 1, 2
source_id    'a post_id / a reply_id, no constraint

Query:

SELECT IF(mention_type = 1,
          (SELECT post_text FROM posts WHERE posts.post_id = source_id),
          (SELECT reply_text FROM replies WHERE replies.reply_id = source_id)
       ) AS text,
       IF(mention_type = 1, 'Post', 'Reply') AS type
FROM mentions
WHERE user_id = @user_id

Solution3

Merge the Post and the Replies relation into a Content relation, and add a column `parent', NULL for posts, and non-NULL ids for replies, indicating which post the reply is for.

user_id    FOREIGN KEY users(user_id)
content_id FOREIGN KEY content(content_id)

Query:

SELECT content_text AS text,
       IF(content_parent = NULL, 'Post', 'Reply') AS type
FROM mentions
INNER JOIN content ON content_id = content.content_id
WHERE user_id = @user_id

Aucun commentaire:

Enregistrer un commentaire