Подтвердить что ты не робот

Facebook, как отслеживание уведомлений (DB Design)

Я просто пытаюсь понять, как структура базы данных Facebook структурирована для отслеживания уведомлений.

Я не буду вдаваться в сложность, как Facebook. Если мы представим простую структуру таблиц для notificaitons:

notifications (id, userid, update, time);

Мы можем получать уведомления друзей, используя:

SELECT `userid`, `update`, `time`
FROM `notifications`
WHERE `userid` IN 
(... query for getting friends...)

Однако какова должна быть структура таблицы, чтобы проверить, какие уведомления были прочитаны, а какие нет?

4b9b3361

Ответ 1

Я не знаю, лучший ли это для этого, но поскольку у меня нет идей от кого-либо еще, это то, что я буду делать. Я надеюсь, что этот ответ может помочь и другим.

У нас есть 2 таблицы

notification
-----------------
id (pk)
userid
notification_type (for complexity like notifications for pictures, videos, apps etc.)
notification
time


notificationsRead
--------------------
id (pk) (i dont think this field is required, anyways)
lasttime_read
userid

Идея состоит в том, чтобы выбирать уведомления из таблицы уведомлений и присоединяться к таблице уведомлений и проверять последнее уведомление и строки чтения с идентификатором > уведомлять. И каждый раз, когда открывается страница уведомлений, обновляйте строку из таблицы уведомлений.

Запрос на непрочитанные уведомления, я думаю, будет таким.

SELECT `userid`, `notification`, `time` from `notifications` `notificationsRead`
WHERE 
`notifications`.`userid` IN ( ... query to get a list of friends ...) 
AND 
(`notifications`.`time` > (
    SELECT `notificationsRead`.`lasttime_read` FROM `notificationsRead` 
    WHERE `notificationsRead`.`userid` = ...$userid...
))

Вышеуказанный запрос не установлен. Благодаря идее дизайна db от @espais

Ответ 2

Вы можете добавить другую таблицу...

tblUserNotificationStatus
-------------------------
- id (pk)
- notification_id
- user_id
- read_status (boolean)

Если вы хотите сохранить историю, вы можете сохранить X последних уведомлений и удалить остальные, которые старше вашего последнего уведомления в списке....

Ответ 3

Если при предоставлении уведомлений вы даете все соответствующие уведомления, доступные в то время, вы можете сделать это проще, добавив отметки времени к уведомляемым событиям и отслеживая, когда каждый пользователь последний раз получал уведомления. Однако, если вы работаете в многосерверной среде, вам нужно быть осторожным в синхронизации. Обратите внимание, что для этого подхода не требуются истинные штампы даты, а только одно, что монотонно возрастает.

Ответ 4

Я вижу, что здесь никто не обращается к факту, что уведомления обычно повторяются, ака. уведомление о предстоящей транзакции всегда будет одинаковым, но с другим идентификатором транзакции или датой в нем. так: {У вас есть новый предстоящий платеж: @paymentID, с установленной датой @dueDate}. Наличие текстов в другой таблице также может помочь с

  • Если вы хотите изменить текст уведомления позже,
  • Сделать многоязычное приложение проще, потому что я могу просто наложить таблицу уведомлений на код языка и получить нужную строку

Таким образом, я также сделал таблицу для тех абстрактных уведомлений, которые просто связаны с пользователем с средней таблицей, где один тип уведомления может быть отправлен одному пользователю несколько раз. Я также связал уведомления с пользователем не с помощью идентификатора внешнего ключа, но я сделал коды уведомлений для всех уведомлений, а full_text проиндексировал поле varchar этих кодов для более быстрой скорости чтения. В связи с тем, что эти уведомления необходимо отправлять в определенное время, разработчику также проще писать

NotificationService::sendNew( Notification::NOTE_NEW_PAYMENT, ['paymentId'] => 123, ['dueDate'] => Carbon::now(), 'userIdToSendTo' );

Теперь, когда мои сообщения собираются иметь в них пользовательские данные, которые вставляются в строку, как вы можете видеть из второго аргумента заранее, я буду хранить их в блоке базы данных. как таковой

$values = base64_encode(serialize($valuesInTextArray));

Это связано с тем, что я хочу отделить уведомления от других таблиц, и поэтому я не хочу ссылаться на необязательные отношения FK из таблицы уведомлений и из нее, так что я могу, например, сказать, что уведомление 234 прикреплено к транзакции 23, а затем присоединяется и получить этот идентификатор транзакции. Развязывание это устраняет накладные расходы на управление этими отношениями. Недостатком является то, что удаление уведомлений почти невозможно, когда, например, удаляется транзакция, но в моем случае я решил, что это все равно не нужно.

Я буду извлекать и заполнять тексты на стороне приложения следующим образом. Ps. Я использую функцию someks vksprintf (https://github.com/washingtonpost/datawrapper/blob/master/lib/utils/vksprintf.php), реквизит для него!

$valuesToFillInString = unserialize(base64_decode($notification->values));
vksprintf( $notificationText->text, $valuesToFillInString )

Обратите внимание, какие поля я индексирую, потому что я собираюсь их найти или отсортировать

Моя конструкция базы данных выглядит следующим образом

==============================

ТАБЛИЦА: Пользователи

  • id (pk)

==============================

ТАБЛИЦА: Уведомления

  • id (pk)
  • user_id (fk, индексированный)
  • text_id (fk - таблица NotificationTexts)
  • значения (blob) [содержащие массив значений для ввода в текстовую строку]
  • createdDateTime (DateTime)
  • read (boolean)

[ClusterIndex] = > (user_id, createdDateTime)

==============================

ТАБЛИЦА: NotificationTexts

  • id (pk)
  • text_id (индексированный uniquem)
  • text (varchar) [{У вас есть новый предстоящий платеж: @paymentID с датой окончания @dueDate}]
  • note (varchar, nullable) [примечания для разработчиков, информационный столбец]

Ответ 5

Ниже приведены таблицы

Пользователь

  • userId (целое число)
  • FULLNAME (VarChar)

Уведомление

  • notificationId (Integer)
  • createDate (Дата)
  • notificationDetailUrl (VarChar)
  • isRead (bollean)
  • описание (VarChar)
  • userId (F.K)