JSON
, вероятно, будет ненужным осложнением.
Эти таблицы приходят на ум:
Posts: post_id, date_uploaded, ...
Tags: post_id, tag (a string) (one row per tag)
Likes: user_id, post_id
Обратите внимание, что Posts: Tags - это 1: многие. То же самое для Лайков.
SELECT ...,
p.date_uploaded,
( SELECT GROUP_CONCAT(tag) FROM Tags
WHERE post_id = p.post_id
AND tag = ?
) AS tags,
IF( EXISTS( SELECT 1 FROM Likes WHERE post_id = p.post_id
AND user_id = ? ),
"they like it",
"they don't like it" ) AS liked
FROM Posts AS p
WHERE ...
Указано:
Tags: INDEX(post_id, tag) -- for "Which Tags does this Post have" (this query)
Tags: INDEX(tag, post_id) -- for "what Posts have this Tag"
Likes: INDEX(user_id, post_id) -- for "what Posts does this user Like"
Likes: INDEX(post_id, user_id) -- for "which users Like this Post"