Hiểu hệ thống thông báo


14

Tôi đã xem xét cách xây dựng một hệ thống thông báo trên SE và các nơi khác và thấy mình bị cuốn hút vào giải pháp đó là câu trả lời được chấp nhận ở đây: /programming/9735578/building-a-notification-system sử dụng cấu trúc này:

╔═════════════╗      ╔═══════════════════╗      ╔════════════════════╗
notification       notification_object      notification_change 
╟─────────────╢      ╟───────────────────╢      ╟────────────────────╢
ID           ║—1:n—→║ID                 ║—1:n—→║ID                  
userID             notificationID           notificationObjectID
╚═════════════╝      object                   verb                
                     ╚═══════════════════╝      actor               
                                                ╚════════════════════╝

Một thông báo là về một cái gì đó (object = event, Friendship ..) đang được thay đổi (verb = thêm, yêu cầu ..) bởi ai đó (diễn viên) và báo cáo cho người dùng (chủ đề). Đây là cấu trúc dữ liệu được chuẩn hóa (mặc dù tôi đã sử dụng MongoDB). Bạn cần thông báo cho người dùng nhất định về những thay đổi. Vì vậy, đó là thông báo cho mỗi người dùng .. có nghĩa là nếu có 100 người dùng tham gia, bạn sẽ tạo ra 100 thông báo.

Lúc đầu tôi nghĩ rằng tôi hiểu cách tiếp cận này, nhưng khi tôi bắt đầu sẵn sàng thực hiện nó, tôi nhận ra rõ ràng là tôi không hiểu rõ lắm. Một số ý kiến ​​cuối cùng về câu trả lời là câu hỏi từ những người dùng khác, những người cũng gặp khó khăn trong việc hiểu giải pháp.

Tôi không chắc đây có phải là mô hình mà tôi sẽ theo dõi không, nhưng với số lượng upvote nó có, tôi chắc chắn rằng nó sẽ có lợi cho tôi để hiểu nó, và tôi chắc chắn muốn tìm hiểu thêm. Tôi hy vọng nó cũng sẽ được sử dụng cho những người gặp khó khăn trong việc nắm bắt giải pháp này (tình cờ, tôi không có đủ điểm internet để để lại nhận xét về câu trả lời đó cho câu hỏi này, bất cứ ai khác làm ơn!)

Câu hỏi

Nếu tôi hiểu đúng, notificationObjectID là chìa khóa trỏ nước ngoài cho notification_object bảng, và notificationID là khóa ngoại trỏ đến các thông báo bảng. Có vẻ như đối tượng phải là khóa ngoại đề cập đến ID của mục nhập cơ sở dữ liệu mà thông báo nói về (ví dụ: một sự kiện hoặc bài đăng cụ thể), nhưng sau đó chúng ta không cần một trường khác để chỉ ra ID đó thuộc về bảng nào?

Tác giả đã viết

notify_object.object xác định loại thay đổi, như chuỗi "tình bạn" Tham chiếu thực tế đến đối tượng đã thay đổi với dữ liệu bổ sung mà tôi nói đến là trong notify_change.notificationObjectID

điều đó dường như không có ý nghĩa với tôi. Đối tượng là một chuỗi (enum?) Và notifyObjectID là một khóa ngoại liên quan đến đối tượng mà thông báo nói về? Sau đó, các bảng giữa và phải được kết nối như thế nào?

Có vẻ như bảng giữa chỉ định đối tượng (hoặc loại đối tượng) mà thông báo nói về, ví dụ như một sự kiện hoặc bài đăng. Sau đó, chúng tôi có thể có nhiều mục trong notify_change trỏ đến cùng một loại đối tượng, cho phép chúng tôi gói thông báo (như "25 người dùng được đăng trên tường của X) - do đó có mối quan hệ 1: n giữa các bảng giữa và phải.

Nhưng tại sao lại có mối quan hệ 1: n giữa các bảng bên trái và giữa? Chúng ta sẽ cung cấp cho "25 người dùng được đăng trên tường của Sam" và "Mary đã cập nhật sự kiện" Thứ sáu dã ngoại "của cô ấy cùng một ID thông báo? Nếu tất cả các thông báo cho cùng một người dùng có cùng ID thông báo, tại sao chúng ta thậm chí cần bảng trên trái?

Một câu hỏi về hiệu suất - nói rằng John đăng bình luận về sự kiện dã ngoại của Mary. Có vẻ như chúng ta cần phải tra cứu để xem liệu notify_object đã tồn tại cho Mary's Picnic trước khi chúng ta tạo mục thông báo_change. Đây có phải là tác động tiêu cực đến hiệu suất, hoặc nó không phải là một vấn đề? Tiếp tục các câu hỏi từ đoạn trước, làm thế nào để chúng ta biết mục thông báo nào để trỏ thông báo_object đến?

Câu trả lời:


8

Cảm ơn vì những câu hỏi thấu đáo như vậy và xin lỗi vì tất cả sự nhầm lẫn - bình luận 1 năm sau câu trả lời ban đầu thật khó khăn và bây giờ 3 năm sau .. những suy nghĩ ban đầu mờ dần và làm tôi bối rối, nhưng tôi sợ phải chỉnh sửa điều đó vì tôi không làm việc về việc lưu trữ thông báo trên phụ trợ ngay bây giờ và không chắc chắn liệu tôi có đánh giá tốt mà không áp dụng thực tế không

Tôi nghĩ tại thời điểm viết:

  • Có và không, notifyID là khóa ngoại, notifyObjectID thì không. Bạn cần một trường FK khác để liên kết các bảng với nhau. Tôi đổ lỗi cho trải nghiệm mongo của tôi khi không rõ ràng về nó :(
  • Có và không, notify_object.object rất mơ hồ vì bạn có thể có nó dưới dạng một chuỗi hoặc một cái gì đó phức tạp (JSON hoặc FK). Trong trường hợp của tôi, nó chỉ là một danh từ.

Vì vậy, tất cả phụ thuộc vào cách thông báo của bạn trông như thế nào. Đối với trường hợp đơn giản, bạn chỉ muốn liên kết toàn bộ thông báo với một số URL, như trang bạn bè - đó là lý do tại sao có đối tượng (entityType) dưới dạng chuỗi là hữu ích - bạn buộc URL vào đó.

Thông báo "bạn có thêm 3 yêu cầu kết bạn " có thể được lưu trữ khác nhau.

Nếu bạn muốn hiển thị từng cái một - bạn sẽ có 3 thông báo, 3 đối tượng thông báo (friend_Vquest) và 3 mục trong notify_change liên kết đến người dùng bạn bè cụ thể.

Nếu bạn muốn hiển thị một thông báo - bạn sẽ có 1 thông báo, 1 / nhiều đối tượng và 3 / nhiều hành động. Vì vậy, trong trường hợp phức tạp này, như «bạn có 3 yêu cầu kết bạn từ người dùng A, người dùng B, người dùng C» - bạn sử dụng notifyObjectID cho mỗi người dùng và có một số liên kết trong văn bản thông báo của bạn.

Bạn nên sử dụng 1 hoặc 3 đối tượng friend_Vquest? Nó phụ thuộc vào

  1. Đối tượng là gì và hành động là gì. Là «bài viết thích / bình luận»? Hoặc là «thích / bình luận thêm» và hệ thống phân cấp đối tượng chỉ được liên kết trong khi hiển thị? Đây là facebook phân biệt «bình luận ảnh» với «đề cập đến người dùng» mà về mặt ngữ nghĩa có vẻ rất gần gũi - bạn có cùng một bức ảnh, cùng một diễn viên nhưng các thông báo khác nhau có thể được hợp nhất với nhau

nhập mô tả hình ảnh ở đây

  1. Bạn có thể xóa một thông báo hoặc bạn cần một lịch sử? Vì vậy, nếu tôi gửi một yêu cầu kết bạn và sau đó hủy nó, hoặc bình luận và sau đó xóa một bài viết, như thế và không giống như một cái gì đó - Nó có nên hiển thị lịch sử này (như một hành động khác) cho người dùng cuối như hai hành động khác nhau không? Chắc là không. Ngoài ra, nó phức tạp hơn về mặt kỹ thuật - bạn cần tìm kiếm nếu có thông báo_object hiện có, thêm thông báo mới vào nó (nếu không - thêm một đối tượng mới) để sau này tôi sẽ cần tìm kiếm qua notify_change để xóa nó. Thay vào đó, tôi chỉ cần thêm một notify_object khác vào cùng một thông báo và xóa nó nếu nó đi cùng với các hành động bị xóa tầng.

Mặt khác, có thể có những trường hợp, trong đó có thể hữu ích khi nhóm các hành động mà không có gì bị xóa khỏi lịch sử.

Tôi nghĩ đó là lý do tại sao tại thời điểm viết, mối quan hệ 1: n giữa các bảng bên trái và giữa đã được thực hiện - để bạn có thể nhóm thông báo không chỉ bởi các tác nhân trên cùng một thực thể (bảng giữa bên phải) mà còn bởi một số đối tượng / thực thể.

Nhưng chắc chắn, bạn có thể đơn giản hóa toàn bộ trường hợp và tối ưu hóa lưu trữ bằng cách đảo ngược mối quan hệ giữa trái sang n: 1, để bạn có thông báo cho mỗi người dùng được tạo cho một sự kiện.

Vì vậy, nó sẽ trông giống như thế này ..

╔═════════════╗      ╔═══════════════════╗      ╔════════════════════╗
notification       notification_object      notification_change 
╟─────────────╢      ╟───────────────────╢      ╟────────────────────╢
ID           ║←—n:1—║ID                 ║—1:n—→║ID                  
noteObjFK          entityType               noteObjFK           
viewerUserID       entityID                 actionOnEntity      
╚═════════════╝      ╚═══════════════════╝      actorUserID         
                                                ╚════════════════════╝

Hy vọng điều này sẽ giúp


Tuyệt vời, cảm ơn vì câu trả lời thấu đáo này. Tôi sẽ xem qua nó và cho bạn biết nếu tôi có thêm câu hỏi nào không, nhưng tôi nghĩ điều này giải thích mọi thứ rất tốt.
dùng45623
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.