2009-12-11 86 views
36

我只是想弄清楚Facebook的数据库是如何构建跟踪通知。Facebook的通知跟踪(DB设计)

我不会像Facebook那么复杂。如果我们想象notificaitons一个简单的表结构:

notifications (id, userid, update, time);

我们可以用得到的朋友通知:

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

然而,应该是什么表结构,以检查出哪些通知已阅读,哪些没有?

回答

35

我不知道这是否是最好的方式来做到这一点,但由于我没有从其他人的想法,这就是我会做的。我希望这个答案也可以帮助其他人。

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

为什么需要此连接?只需将阅读字段放在通知表中,您就可以节省时间和空间。 – ash 2010-07-13 14:17:07

+1

'notificationsread'表格将为每个用户只存储1行。当用户将他的通知发送到最近的通知ID时,哪个会被更新。 所以我们实际上并不需要这个领域本身。感谢您的评论:) – 2010-07-14 15:08:15

+1

我觉得'Jasie'的意思是说,为什么你甚至需要'notificationRead'表。只在''notification'表中添加'readStatus'字段是否有问题?因此,当通知创建时,其'readStatus'为false,并且只有在用户打开通知页面时才变为'true'。更新了 – 2010-09-23 16:32:59

9

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

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

如果你想保持一个历史,你可以保持X最新通知,并删除其余的是比在列表中的最后通知年长.. ..

+0

所以我们对这个表时将通知加行是创建还是当用户读取通知? – 2009-12-11 15:43:32

+0

我会想象,当你有一个通知创建,这张表会被更新以及...一旦你的用户查看通知,你会将read_status字段从false更新为true – espais 2009-12-11 22:16:47

+0

这意味着当添加通知时,我们需要找到用户朋友并在第二个表格右侧插入所有这些行。但问题产生的原因是通知后发出的好友请求。通知后的朋友不会在tblUserNotificationStatus – 2009-12-12 04:25:28

7

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

+0

准确!为什么我以前没有这样想,只需在用户表中添加一个notification_sync字段,并仅为通知表使用一个表。我想这是最好的实施..感谢兄弟,你的回答是 – 2009-12-12 14:45:27

+0

不客气。 – 2009-12-13 03:51:24

+0

根据这个设计,答案是否如下? – 2010-09-22 19:31:31

0

用户

  • 用户id(整数)
  • 全名(VARCHAR)

通知

  • notificationId(整数)
  • creationDate(日期)
  • notificationDetailUrl(VARCHAR)
  • isRead(bollean)
  • 描述(VARCHAR)
  • 用户id(FK)
2

我看到这里没有人解决这个事实,通知通常会重新发生,也就是说。即将到来的交易通知总是相同的,但具有不同的交易ID或日期。因此:{你有一个新的即将到来的付款:@paymentID,截止日期为@dueDate}。 在不同的表有文本也可以

  1. 帮助,如果你想以后更改通知文本上
  2. 使得应用多语种更容易,因为我只是一个语言代码层通知表和检索合适的串

因此我也作了表为那些抽象通知,这是刚下用户连接用中间表,其中一个通知类型可以在多个时间发送到一个用户。我还将通知链接到用户,而不是通过外键ID,但是我为所有通知和full_text编制了索引这些代码的varchar字段的通知代码,以提高读取速度。由于这样的事实,这些通知需要在指定的时间发送,也更容易为开发人员编写

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

现在,因为我的消息都将在他们的自定义数据,插入到字符串,正如你可以从第二个参数中预先看到的那样,那么我将它们存储在一个数据库blob中。这样

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

这是因为我希望去耦其他表的通知,因此我不想克里特unnessecary从和通知表FK关系,这样我就可以例如说,通知234连接到交易23,然后加入并获得该交易ID。解耦可以消除管理这些关系的开销。缺点是,删除通知时几乎不可能,例如删除一个事务时,但在我的用例中,我决定,这不是必需的。

我将按照以下方式检索并填充App端的文本。 PS。我正在使用某人的vksprintf函数(https://github.com/washingtonpost/datawrapper/blob/master/lib/utils/vksprintf.php),道具给他!

$valuesToFillInString = unserialize(base64_decode($notification->values)); 
vksprintf($notificationText->text, $valuesToFillInString) 

还要注意哪些字段I指数,因为我要找到或排序它们

我的数据库设计如下

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

表:用户

  • ID(PK)

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

表:通知

  • ID(PK )
  • USER_ID(FK,索引)
  • text_id(FK - NotificationTexts表)
  • 值(BLOB)[含有值的阵列,以输入到所述文本串]
  • createdDateTime(日期时间)
  • 读取(布尔值)

[ClusterIndex] =>(USER_ID,createdDateTime)

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

表:NotificationTexts

  • ID(PK)
  • text_id(uniquem索引)
  • 文本(VARCHAR){你有一个即将到来的新的支付:@paymentID,与@dueDate的到期日}]
  • 说明(VARCHAR,可为空)笔记开发人员,信息栏]