Всем привет! Пытаюсь реализовать ленту событий как вконтакте на php и mysql.
Суть такая... У меня (пользователя) есть комментарии, посты, фотографии. Нужно сделать ленту типа:
- Пользователь такой-то ответил на ваш комментырий.
- Пользователю такому-то понравилась ваша фотография.
- Пользователю понравился ваш комментарий.
- Пользователь такой-то принял заявку в друзья.
В сети и на тостере уже много тем перелопатил, но все или отдаленно или совсем не то. Как хранить данные для такого вывода? Решил сделать так:
При публикации комментария, или установке лайка или принятии заявки в друзья, в таблицу feed_events добавляем, `id действующего юзера`, `id того, чья запись и лента`, `id записи`, `текст который отобразится в ленте`. Его придется генерировать на стадии записи в БД. Например если это лайк к фотографии, то пишем в это поле "понравилась фотография"
если это ответ на комментарий - пишем "ответил на ваш комментарий" и т.д.
Что вы думаете? Правильный ли это подход?
И вот еще проблема. При выводе самого события хотелось бы выводить и ссылку на пост, комментарий, фотографию с которой событие связано... Как в этом случае хранить ссылку? Просто как готовая ссылка - это вариант, но если например захочется вывести превью фотографии к которой написали комментарий, то тут було бы целесообразней хранить её id. Тут сталкиваюсь с проблемой, ведь это может быть и id фотографии и id комментария и id поста. Как тогда JOIN-ить нужную таблицу?
id, userId, entityId, entityType, createdAt, updatedAt
Как то так можно.
Т.к.
id - УН записи
userId - УН пользователя
entityId - УН записи/лайка/etc...
entityType - тип сущности (post, like, msg ....)
createdAt - дата создания
updatedAt - дата обновления (т.е. когда юзер прочел уведомление)
Соответственно, если есть/отличается updatedAt, то не выводим.
Можно добавить id пользователя который запостил/лайкнул
Программа видит что есть новые не прочтенные записи, смотрит кому отображать, какую сущность взять (фото, пост и т.д.)
Все зависит от конкретной подачи информации.
Спасибо. А как в этом случае получить, например, заголовок поста, к которому произошло событие?
Например получится такой запрос:
SELECT id, userId, entityId, entityType, createdAt, updatedAt FROM `feed` LEFT JOIN ????? ON `feed`.`entityId` = ???????.`id`
Doc: Получается, чтобы создать ленту из всех событий со ссылками на посты, фотографии, комментарии... Нужно будет сделать для каждого такого случая свой запрос и соединить все вместе в php?
Doc: Как? Ведь мы не знаем о каждом событии при запросе списка событий. Выходит придется сделать вот так:
SELECT feed.*, posts.title FROM feed LEFT JOIN posts ON feed.entityId = posts.id WHERE feed.entityType = "posts"
SELECT feed.*, photos.title FROM feed LEFT JOIN photos ON feed.entityId = photos.id WHERE feed.entityType = "photos"
SELECT feed.*, comments.title FROM feed LEFT JOIN comments ON feed.entityId = comments.id WHERE feed.entityType = "comments"
SELECT feed.*, users.title FROM feed LEFT JOIN users ON feed.entityId = users.id WHERE feed.entityType = "users"
И так далее. Для каждого возможного случая.... Ведь событие может произойти не только с постом (лайк), но и с комментариями (лайк, ответ), фотографиями (лайк, комментарий, отметка), пользователем (подписка)
Евгений: Да, для каждой сущности выбираете все что вам потребуется и отображаете.
Если нагрузка будет возрастать (1000+ запросов в минуту), то тут стоит продумать архитектуру.
Но я этим не буду заниматься, мне своего хватает.
Я кстати использую mongodb. Но и система немного друга.
На любой чих в проекте создается лог и из него ясно, кто что сделал.
Уведомления сидят в комнатах на websockets. Сервер для уведомления, мессенджера и т.д., написан на Go.
Весь остальной бекенд в проекте крутится на php 7.1 / mysql, SF3+DDD+Bus+CQRS
Фронтенд, это совершенно отдельный сайт, реализованный на js/ts (angular)? который общается с беком по api.