Facebook喜欢通知跟踪(数据库设计)

时间:2009-12-11 11:58:57

标签: mysql database-design data-modeling

我只想弄清楚Facebook的数据库是如何构建用于跟踪通知的。

我不会像Facebook那样复杂化。如果我们想象一个简单的通知表结构:

notifications (id, userid, update, time);

我们可以使用以下方式收到朋友的通知:

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

但是,表格结构应该是什么来检查哪些通知已经被读取?哪些通知没有?

6 个答案:

答案 0 :(得分:38)

我不知道这是否是最好的方法,但由于我没有得到任何人的想法,这就是我要做的。我希望这个答案也可以帮助其他人。

我们有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

我们的想法是从通知表中选择通知并加入notificationsRead表并检查上次读取的通知以及ID为>的行。 notificationid。每次打开通知页面时,都会更新notificationsRead表中的行。

查询未读通知我猜想会是这样的..

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...
))

未检查上述查询。 感谢@espais的db设计理念

答案 1 :(得分:9)

你可以添加另一张表......

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

如果您想保留历史记录,可以保留X最新通知,并删除比您在列表中的上次通知旧的剩余通知....

答案 2 :(得分:7)

如果在您发出通知时,您提供当时可用的所有相关通知,则可以通过将时间戳附加到可通知事件并跟踪每个用户上次收到通知的时间来简化此操作。但是,如果您处于多服务器环境中,则必须注意同步。请注意,此方法不需要真正的日期时间戳,只需要单调增加。

答案 3 :(得分:3)

我看到这里没有人解决这个事实,通知通常是重新发生的,也就是说。即将发生的交易的通知总是相同的,但其中包含不同的交易ID或日期。如此:{您有一个新的即将付款:@paymentID,截止日期为@dueDate}。 将文本放在不同的表格中也可以提供帮助

  1. 如果您想稍后更改通知文本
  2. 使应用程序多语言更容易,因为我可以使用语言代码对通知表进行分层并检索相应的字符串
  3. 因此,我还为那些抽象通知创建了一个表,这些通知只是在用户下面与中间表链接,其中一个通知类型可以多次发送给一个用户。我还将通知链接到用户而不是外键ID,但是我为所有通知编写了通知代码,并且full_text索引了这些代码的varchar字段,以提高读取速度。由于这些通知需要在特定时间发送,因此开发人员也更容易编写

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

    现在,由于我的消息将在其中包含自定义数据,即插入到字符串中,正如您可以从第二个参数中预先看到的那样,然后我将它们存储在数据库blob中。就这样

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

    这是因为我想要将通知与其他表分离,因此我不想从通知表中创建无关的FK关系,因此我可以说通知234附加到事务23然后加入并获得该交易ID。解耦这会消除管理这些关系的开销。缺点是,删除通知几乎是不可能的,例如删除了一个事务,但在我决定使用的情况下,无论如何都不需要这样做。

    我将在App端检索并填写文本,如下所示。 PS。我正在使用someones 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,indexed)
    • text_id(fk - NotificationTexts表)
    • values(blob)[包含要输入到文本字符串中的值数组]
    • createdDateTime(DateTime)
    • 读(布尔)

    [ClusterIndex] => (user_id,createdDateTime)

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

    表:NotificationTexts

    • id(pk)
    • text_id(uniquem indexed)
    • text(varchar)[{您有一个新的即将付款:@paymentID,截止日期为@dueDate}]
    • note(varchar,nullable)[开发人员注意事项,信息栏]

答案 4 :(得分:0)

表格如下

用户

  • userId(整数)
  • 全名(VARCHAR)

<强>通知

  • notificationId(整数)
  • creationDate(Date)
  • notificationDetailUrl(VarChar)
  • isRead(bollean)
  • description(VarChar)
  • userId(F.K)

答案 5 :(得分:0)

我还试图弄清楚如何设计通知系统。关于通知状态(已读,未读,已删除,已存档等),我认为 ENUM 的最佳选择。我认为,除了READ和UNREAD之外,可能会有超过两种不同类型的状态,例如已删除,已存档,已看到,已关闭,等等。

这将使您随着需求的发展而扩展。

我还认为(至少在我的情况下)拥有一个字段来存储操作网址或链接可能是有意义的。某些通知可能要求或提示用户跟随链接。

如果您要使用其他类型的通知,则也可以使用通知类型。我认为可能会有系统通知(例如验证电子邮件通知)和用户提示的通知(例如朋友请求)。

我认为这是拥有体面的通知系统的最低要求。

users
-------------
id
username
password
email

notifications
-------------
id
user_id (fk)
notification_type (enum)
notification_status (enum)
notification_action (link)
notification_text
date_created (timestamp)