Понимание системы уведомлений


15

Я изучал, как построить систему уведомлений на SE и в других местах, и нашел себя заинтересованным в решении, которое является здесь принятым ответом: /programming/9735578/building-a-notification-system, в котором используется эта структура:

╔═════════════╗      ╔═══════════════════╗      ╔════════════════════╗
notification       notification_object      notification_change 
╟─────────────╢      ╟───────────────────╢      ╟────────────────────╢
ID           ║—1:n—→║ID                 ║—1:n—→║ID                  
userID             notificationID           notificationObjectID
╚═════════════╝      object                   verb                
                     ╚═══════════════════╝      actor               
                                                ╚════════════════════╝

Уведомление о том, что кто-то (субъект) что-то (объект = событие, дружба ..) был изменен (глагол = добавлен, запрошен ..) и передан пользователю (субъекту). Вот нормализованная структура данных (хотя я использовал MongoDB). Вам необходимо уведомить определенных пользователей об изменениях. Таким образом, это уведомления для каждого пользователя. Это означает, что если в нем участвует 100 пользователей, вы создаете 100 уведомлений.

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

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

Вопросов

Если я правильно понимаю, тоtificationObjectID - это внешний ключ, указывающий на таблицу Notification_object , а NotificationID - это внешний ключ, указывающий на таблицу уведомлений . Кажется, что объект должен быть внешним ключом, ссылающимся на идентификатор записи базы данных, о которой идет уведомление (например, конкретное событие или сообщение), но не нужно ли нам тогда другое поле, чтобы указать, к какой таблице принадлежит этот идентификатор?

Автор написал

Notification_object.object идентифицирует тип изменения, например, строку «дружба». Фактическая ссылка на измененный объект с его дополнительными данными, о которых я говорю, находится в messages_change.notificationObjectID.

что, кажется, не имеет смысла для меня. Object - это строка (enum?), АtificationObjectID - это внешний ключ, ссылающийся на объект, о котором идет уведомление? Тогда как связаны средняя и правая таблицы вообще?

Кажется, что средняя таблица указывает, о каком объекте (или типе объекта) идет уведомление, например, о событии или посте. Тогда мы можем иметь много записей в messages_change, которые указывают на один и тот же тип объекта, что позволяет нам связывать уведомления (например, «25 пользователей, размещенных на стене X) - отсюда и соотношение 1: n между средней и правой таблицами.

Но почему между левой и средней таблицами существует соотношение 1: n? Собираемся ли мы дать «25 пользователям, размещенным на стене Сэма», а «Мария обновила свое событие« Пятничный пикник ») с одним и тем же идентификатором уведомления? Если все уведомления для одного и того же пользователя имеют одинаковый идентификатор уведомления, зачем нам даже таблица на осталось?

Вопрос производительности - скажем, Джон публикует комментарий к мероприятию Марии Пикник. Похоже, что нам нужно было бы выполнить поиск, чтобы увидеть, существует ли объект Notification_object для Пикника Мэри, прежде чем мы создадим запись Notification_change . Это отрицательно скажется на производительности или это не проблема? Продолжая вопросы из предыдущего параграфа, как мы узнаем, на какую запись уведомления будет указывать объект уведомлений ?

Ответы:


8

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

Я думаю на момент написания:

  • Да и нет, NotificationID был внешним ключом, Notification_bjectID не был. Вам нужно другое поле FK, чтобы связать таблицы. Я обвиняю мой опыт монго в том, что я не настолько ясен об этом :(
  • Да и нет, Notification_object.object является расплывчатым, потому что вы можете иметь его просто в виде строки или чего-то сложного (JSON или FK). В моем случае это было просто существительное.

Так что все зависит от того, как выглядят ваши уведомления. В простом случае вы просто хотите связать все уведомление с каким-либо URL-адресом, например со страницей друзей, - поэтому полезно иметь в качестве строки объект (entityType) - вы привязываете к нему URL-адреса.

Уведомление «у вас есть 3 добавленных запроса на добавление в друзья » может храниться по-другому

Если вы хотите показывать их по одному - у вас будет 3 уведомления, 3 объекта уведомления (friend_request) и 3 записи в messages_change, которые ссылаются на конкретного друга-пользователя.

Если вы хотите показать одно уведомление - у вас будет 1 уведомление, 1 / более объектов и 3 / более действий. Таким образом, в этом сложном случае, например, «у вас есть 3 запроса на добавление в друзья от пользователя A, пользователя B, пользователя C» - вы используете ID для уведомлений для каждого пользователя и имеете несколько ссылок в тексте уведомления.

Вы должны использовать 1 или 3 объекта friend_request? Это зависит от

  1. Что такое объект и что такое действие. «Статья понравилась / прокомментирована»? Или это «нравится / комментарий добавлен» и иерархия объектов связывается только во время отображения? Вот Facebook, отличающий «комментирование фотографий» от «упоминания пользователей», которые семантически кажутся очень близкими - у вас одна и та же фотография, один и тот же актер, но разные уведомления, которые могли бы быть объединены вместе

введите описание изображения здесь

  1. Вы можете удалить уведомление или вам нужна история? Так что, если я отправлю запрос на добавление в друзья, а затем откажусь от него, или оставлю комментарий, а затем удалю статью, как, а затем, в отличие от чего-либо, - должен ли он показывать эту историю (как другое действие) конечному пользователю как два разных действия? Возможно нет. Кроме того, он технически более сложен - вам нужно выполнить поиск, если существует существующий объект уведомлений, добавить к нему новый уведомлений (если нет - добавить новый объект), чтобы позже мне пришлось искать в уведомлении обмен, чтобы удалить его. Вместо этого я просто добавил бы к этому уведомлению еще один объект уведомлений и удалил бы его, если его нет с действиями, удаляемыми каскадом.

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

Я думаю, именно поэтому во время написания было сделано соотношение 1: n между левой и средней таблицами, чтобы вы могли группировать уведомления не только по субъектам одной и той же сущности (средне-правой таблицы), но и по нескольким объектам / сущностям.

Но, конечно, вы можете упростить весь случай и оптимизировать хранилище, изменив отношение левого-среднего к n: 1, так что вы получите уведомления для каждого пользователя, сгенерированные для одного события.

Чтобы это выглядело больше так ...

╔═════════════╗      ╔═══════════════════╗      ╔════════════════════╗
notification       notification_object      notification_change 
╟─────────────╢      ╟───────────────────╢      ╟────────────────────╢
ID           ║←—n:1—║ID                 ║—1:n—→║ID                  
noteObjFK          entityType               noteObjFK           
viewerUserID       entityID                 actionOnEntity      
╚═════════════╝      ╚═══════════════════╝      actorUserID         
                                                ╚════════════════════╝

Надеюсь, это помогло


Отлично, спасибо за этот исчерпывающий ответ. Я пройду через это и дам вам знать, если у меня возникнут еще вопросы, но я думаю, что это очень хорошо объясняет.
user45623
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.