Как спроектировать ленту активности?

Всем привет!
Есть сайт, соцсеть.

На сайте есть личные записи пользователей(записи личного блога), комментарии, альбомы с фото.
Для хранения в БД используется Doctrine.

Нужно спроектировать ленту активности.

Сейчас сделано так: при создании чего либо (коммента к фотке, коммента к записи пользователь, фотки,записи пользователя) , создаётся сущность ( AlbumImageCommentActivity, ArticleCommentActivity, AlbumImageActivity,ArticleActivity соответственно, унаследованная от базовой Activity). Всё бы ничего, но при выводе на страницу мешает приватность (а у комментариев её вообще нет) и на этапе выборки из БД я не могу отсеять те активности которые не доступные пользователю. Сейчас же отсеиваю уже после выборки (просто удаляю из массива, если не прошло проверку на доступность), здесь есть минус в том, что ломается пагинация (на каждой странице может быть разное кол-во элементов, а то и вообще не быть), но благо лента подгрузкой, как в ВК.

Возможно изначально я пошёл не потому пути.
Ваши предложения? :)

Да и вообще, как делается вывод сущностей разных классов в одном списке?
  • Вопрос задан
  • 442 просмотра
Пригласить эксперта
Ответы на вопрос 1
iqw
@iqw
Serior Software Engineer
Я бы делал следующим образом: сделал бы систему ивентов, например - создалась страница, добавлен коммент, и когда происходит одно из этих собитый - тригерится ивент, обработчик его ловит, пишет основные данные в отдельную таблицу (что-то типо EventLog), поля, которые содержит эта таблица - user_id(int), date(datetime), event_type(tinyint), triggered_on(int), где user_id айди юзера, с привязкой его в энтити напрямую, date - дата события, event_type - константа типа ивента (описать можно константами или другим удобным способом, я бы, например, делал дискриминатором по полю event_type с под-сущностями, каждая из которых будет иметь привязку на свой ожидаемый тип сущности, наследуя геттеры, тут есть большое пространство для улучшения взаимодействия), triggered_on - id записи в базе, которая была создана-обновлена etc. После этого имеем список всего, что делал юзер, таблица достаточно простая, логирование можно расширять.
Данный этап вносит некую денормализацию данных, чтобы упростить их поиск.

Этап второй - выборка. Тут строится нехитрый запрос, который исключает данные, что этому пользователю не надо.
Джойном подгружается сущность юзера, остальные данные можно получить на момент рендера этого списка (если есть дискриминатор, предложенный выше, запросив что-то типо {{ eventLog.triggeredOn.title }}).

Пример - выбираем все данные в каком то спектре (пагинация) с иннерджойном на таблицу подписок юзера на другого юзера, выйдет что ивенты юзеров, на которые текущий юзер не подписан не попадают в выборку уже на уровне самого запроса, что позволяет пагинировать нормально, не вгоняя в память огромного числа данных.
Этот механизм можно заточить под множество вариаций, если надо больше перфоманса - тут надо думать в сторону грамотного распределения данных, например слать их в какой-то elasticsearch, но потом запросы становяться сложнее.

В любом случае, построение эффективной бизнес-логики - зависит от всех нюансов задачи, того финальный результат составлять Вам, такие задачи никто не решит в ответ на вопрос на Question-Answer сайте :)
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы