【问题标题】:Facebook like notifications tracking (DB Design)Facebook 喜欢通知跟踪(数据库设计)
【发布时间】:2010-12-25 15:32:58
【问题描述】:

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

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

notifications (id, userid, update, time);

我们可以通过以下方式获取朋友的通知:

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

但是,应该使用什么样的表结构来检查哪些通知已被阅读,哪些尚未被阅读?

【问题讨论】:

    标签: mysql database-design data-modeling


    【解决方案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
    

    这个想法是从通知表中选择通知并加入通知读取表并检查最后读取的通知和 ID > notificationid 的行。并且每次打开通知页面时都会更新 notificationRead 表中的行。

    我猜未读通知的查询应该是这样的..

    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 的数据库设计理念

    【讨论】:

    • 为什么需要这个连接?只需将读取字段放在通知表中,您就可以节省时间和空间。
    • notificationsread 表将为每个用户仅存储 1 行。当用户查看他的最新通知ID的通知时,这将被更新。所以我们实际上并不需要那个字段本身。感谢您的评论:)
    • 我认为Jasie 的意思是,为什么你甚至需要notificationRead 表。将readStatus 字段添加到您的notification 表中是否有问题。所以当一个通知创建时,它的readStatus为假,只有当用户打开通知页面时才转为true
    • 已更新。 notificationRead 将记录用户上次查看通知的时间,并将所有其他通知显示为未读。
    • 如果你不想要第二个表,你可以将最后读取的属性保存在用户表上,例如
    【解决方案2】:

    您可以添加另一个表...

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

    如果您想保留历史记录,您可以保留 X 个最新通知并删除列表中比您的最后一个通知更早的其余通知....

    【讨论】:

    • 所以我们在创建通知或用户阅读通知时在此表上添加行?
    • 我想当您创建通知时,此表也会更新...一旦您的用户查看通知,您会将 read_status 字段从 false 更新为 true
    • 这意味着当添加通知时,我们需要找到用户朋友并将所有这些行插入到第二个表中。但是出现的问题是在通知之后提出的好友请求。收到通知后结交的朋友不会在 tblUserNotificationStatus 中出现他们的行
    • 我猜你的答案不是我真正想要的,但它给了我一个很大的提示。
    【解决方案3】:

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

    【讨论】:

    • 没错!为什么我之前没有想到,只需在 user 表中添加一个 notification_sync 字段,并且只使用一个表作为通知表。我想这是最好的实现方式。谢谢兄弟,你的就是答案
    • 下面的答案是基于这个设计的吗?
    【解决方案4】:

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

    1. 如果您想稍后更改通知文本
    2. 使应用程序多语言化更容易,因为我可以只使用语言代码对通知表进行分层并检索适当的字符串

    因此我还为那些抽象通知制作了一个表格,它们只是在用户下方与一个中间表格链接,其中一种通知类型可以多次发送给一个用户。我还不是通过外键 ID 将通知链接到用户,但我为所有通知制作了通知代码,并且全文索引了这些代码的 varchar 字段,以加快阅读速度。由于这些通知需要在特定的时间发送,开发者也更容易编写

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

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

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

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

    我将在 App 端检索并填写文本如下。附言。我正在使用某人的 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(日期时间)
    • 读取(布尔值)

    [ClusterIndex] => (user_id, createdDateTime)

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

    表格:通知文本

    • id (pk)
    • text_id(唯一索引)
    • text (varchar) [{ 您有一笔新的即将付款:@paymentID,到期日为@dueDate }]
    • note(varchar,可为空)[开发人员说明,信息栏]

    【讨论】:

      【解决方案5】:

      我也在试图弄清楚如何设计一个通知系统。关于通知状态(已读、未读、已删除、已归档等),我认为它是 ENUM 的一个很好的候选者。我认为除了 READ 和 UNREAD 之外,可能会有两种以上不同类型的状态,例如已删除、已归档、已查看、已解雇等。

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

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

      如果您想要不同的类型,也可以设置通知类型。我认为可能会有系统通知(例如验证电子邮件通知)和用户提示通知(例如好友请求)。

      这是我认为拥有一个像样的通知系统的最低限度的结构。

      users
      -------------
      id
      username
      password
      email
      
      notifications
      -------------
      id
      user_id (fk)
      notification_type (enum)
      notification_status (enum)
      notification_action (link)
      notification_text
      date_created (timestamp)
      

      【讨论】:

        【解决方案6】:

        表格如下

        用户

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

        通知

        • notificationId(整数)
        • creationDate(日期)
        • notificationDetailUrl (VarChar)
        • isRead (bollean)
        • 说明 (VarChar)
        • userId (F.K)

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2013-12-24
          • 1970-01-01
          • 2020-05-30
          • 1970-01-01
          • 1970-01-01
          • 2012-08-02
          • 2012-08-27
          相关资源
          最近更新 更多