2009-12-11 82 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,可爲空)筆記開發人員,信息欄]