了解通知系统


15

我一直在研究如何在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               
                                                ╚════════════════════╝

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

起初我以为我了解这种方法,但是当我准备开始实施它时,我意识到我显然不太了解它。关于答案的最后几条评论是来自其他用户的问题,这些用户也难以理解解决方案。

我不确定这是否是我最终会遵循的模型,但是鉴于它所拥有的支持者数量,我相信这对我有所帮助,我当然希望了解更多。我希望这对于其他在掌握该解决方案方面遇到困难的人也将是有用的(顺便说一句,我没有足够的互联网积分就该问题的答案发表评论,其他任何人都可以做!)

问题

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

作者写道

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

这对我来说似乎没有意义。对象是一个字符串(枚举?),notificationObjectID是一个外键,指向通知所针对的对象?那么中间表和右边表是如何连接的呢?

似乎中间表指定了通知涉及的对象(或对象类型),例如事件或帖子。然后,在notification_change中可以有许多条目指向相同的对象类型,这使我们可以捆绑通知(例如“在X的墙上张贴了25位用户”)-因此,中间表和右表之间是1:n关系。

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

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

Answers:


8

感谢您提出如此彻底的问题,并为所有的困惑感到抱歉-最初回答后1年很难发表评论,而现在则是3年后发表评论。.最初的想法也逐渐淡化并使我感到困惑,但是我害怕编辑漏洞,因为我没有工作立即在后端存储通知,不确定是否可以在没有实际应用的情况下做出正确的判断

我认为在撰写本文时:

  • 是和否,notificationID是一个外键,notificationObjectID不是。您确实需要另一个FK字段将表绑定在一起。我指责我的蒙哥经验不那么清楚:(
  • 是的,不是,notification_object.object含糊不清,因为您可以将其作为字符串或其他复杂形式(JSON或FK)使用。就我而言,这只是一个名词。

因此,这完全取决于您的通知外观。对于简单的情况,您只想将整个通知链接到某个URL,例如好友页面-这就是为什么将对象(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         
                                                ╚════════════════════╝

希望这有所帮助


太好了,谢谢您的彻底回答。我将仔细研究它,并让您知道是否还有其他问题,但是我认为这可以很好地说明问题。
user45623 2015年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.