了解通知系统

use*_*623 18 database-design

我一直在研究如何在 SE 和其他地方构建通知系统,并发现自己被这里接受的答案所吸引:https : //stackoverflow.com/questions/9735578/building-a-notification-system 使用这种结构:

???????????????      ?????????????????????      ??????????????????????
?notification ?      ?notification_object?      ?notification_change ?
???????????????      ?????????????????????      ??????????????????????
?ID           ?—1:n—??ID                 ?—1:n—??ID                  ?
?userID       ?      ?notificationID     ?      ?notificationObjectID?
???????????????      ?object             ?      ?verb                ?
                     ?????????????????????      ?actor               ?
                                                ??????????????????????
Run Code Online (Sandbox Code Playgroud)

通知是关于某事(对象 = 事件、友谊..)被某人(演员)更改(动词 = 添加、请求..)并报告给用户(主题)。这是一个规范化的数据结构(尽管我使用过 MongoDB)。您需要将更改通知某些用户。所以它是每个用户的通知......意味着如果有 100 个用户参与,你会生成 100 个通知。

起初我以为我理解这种方法,但是当我开始准备实施它时,我意识到我显然不是特别了解它。对答案的最后几条评论是其他用户在理解解决方案时遇到的问题。

我不确定这是否是我最终会遵循的模型,但考虑到它拥有的赞成票数量,我相信理解它会对我有益,而且我当然想了解更多。我希望这对在掌握此解决方案时遇到困难的其他人也有用(顺便说一句,我没有足够的互联网点来对针对此问题的答案发表评论,请其他人做!)

问题

如果我的理解对不对,notificationObjectID是一个外键指向notification_object表,notificationID是一个外键指向通知表。似乎object应该是一个外键,指的是通知所涉及的数据库条目的 ID(例如特定的事件或帖子),但是我们不需要另一个字段来指示该 ID 属于哪个表吗?

作者写道

Notification_object.object 标识更改类型,如字符串“friendship”。我所讨论的对已更改对象及其额外数据的实际引用在 notification_change.notificationObjectID 中

这对我来说似乎没有意义。Object 是一个字符串(枚举?),notificationObjectID 是一个外键,指的是通知所涉及的对象?那么中间和右边的桌子到底是怎么连接的呢?

中间的表格似乎指定了通知是关于什么对象(或对象类型),例如事件或帖子。然后我们可以在notification_change中有许多指向相同对象类型的条目,这允许我们捆绑通知(例如“25 个用户发布在 X 的墙上)——因此中间表和右表之间的 1:n 关系。

但是为什么左表和中表之间是 1:n 的关系呢?我们是否要给“张贴在山姆的墙上的 25 个用户”和“玛丽更新了她的“星期五野餐”事件相同的通知 ID?如果同一用户的所有通知都具有相同的通知 ID,为什么我们甚至需要在剩下?

一个性能问题 - 假设约翰对玛丽的野餐活动发表了评论。在创建notification_change条目之前,似乎我们需要进行查找以查看Mary's Picnic的notification_object 是否已经存在。这是否会对性能产生负面影响,还是不是问题?继续前一段的问题,我们怎么会知道哪个通知条目指向notification_object什么?

小智 8

感谢您提出如此详尽的问题,并为所有的困惑感到抱歉 - 在最初的答案后 1 年评论很难,现在 3 年后......最初的想法逐渐消失并使我感到困惑,但我害怕编辑漏洞,因为我没有工作关于现在在后端存储通知并且不确定我是否在没有实际应用的情况下做出好的判断

我在撰写本文时认为:

  • 是与否,notificationID 是外键,notificationObjectID 不是。您确实需要另一个 FK 字段来将表联系在一起。我责怪我的 mongo 经验没有那么清楚:(
  • 是与否,notification_object.object 是模糊的,因为您可以将其作为字符串或复杂的东西(JSON 或 FK)来使用。就我而言,它只是一个名词。

因此,这一切都取决于您的通知的外观。对于简单的情况,您只想将整个通知链接到某个 URL,例如朋友页面 - 这就是为什么将 object (entityType) 作为字符串是有用的 - 您将 URL 绑定到它。

通知“您添加了3 个好友请求”可以不同方式存储。

如果您想一次向他们显示一个 - 您将有 3 个通知、3 个通知对象(friend_request)和 notification_change 中的 3 个条目,这些条目链接到特定的朋友用户。

如果您想显示一个通知 - 您将有 1 个通知、1 个/多个对象和 3 个/多个操作。因此,在这种复杂的情况下,例如“您有来自用户 A、用户 B、用户 C 的 3 个好友请求”——您为每个用户使用了 notificationObjectID,并且在通知文本中有多个链接。

你应该使用 1 个还是 3 个friend_request 对象?这取决于

  1. 什么是对象,什么是动作。«文章喜欢/评论»?或者是“添加了喜欢/评论”并且对象层次结构仅在显示期间链接?这是 Facebook 将“照片评论”与“用户提及”区分开来,它们在语义上似乎非常接近——你有相同的照片,相同的演员,但不同的通知可以合并在一起

在此处输入图片说明

  1. 您可以删除通知还是需要历史记录?因此,如果我发送好友请求然后取消它,或者评论然后删除一篇文章,喜欢然后不喜欢某事 - 它是否应该将此历史记录(作为另一个动作)作为两个不同的动作显示给最终用户?可能不是。此外,它在技术上更复杂-您需要搜索是否存在notification_object,向其添加新的notification_change(如果没有-添加新对象),以便稍后我需要通过notification_change 进行搜索以将其删除。相反,我只是将另一个 notification_object 添加到同一个通知中,如果它的动作被级联删除,则将其删除。

另一方面,在某些情况下,对没有从历史中擦除的操作进行分组可能会很有用。

我认为这就是为什么在撰写本文时,已完成左表和中表之间的 1:n 关系 - 这样您不仅可以按同一实体(中右表)上的参与者分组通知,还可以按多个对象/实体分组通知。

但是可以肯定的是,您可以通过将左中关系反转为 n:1 来简化整个案例并优化存储,以便为一个事件生成每个用户的通知。

这样它看起来更像这样..

???????????????      ?????????????????????      ??????????????????????
?notification ?      ?notification_object?      ?notification_change ?
???????????????      ?????????????????????      ??????????????????????
?ID           ??—n:1—?ID                 ?—1:n—??ID                  ?
?noteObjFK    ?      ?entityType         ?      ?noteObjFK           ?
?viewerUserID ?      ?entityID           ?      ?actionOnEntity      ?
???????????????      ?????????????????????      ?actorUserID         ?
                                                ??????????????????????
Run Code Online (Sandbox Code Playgroud)

希望这有帮助