Memahami sistem notifikasi

15

Saya telah mencari cara untuk membangun sistem notifikasi pada SE dan di tempat lain dan menemukan diri saya tertarik pada solusi yang merupakan jawaban yang diterima di sini: /programming/9735578/building-a-notification-system yang menggunakan struktur ini:

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

Pemberitahuan adalah sesuatu (objek = acara, pertemanan ..) sedang diubah (kata kerja = ditambahkan, diminta ..) oleh seseorang (aktor) dan dilaporkan kepada pengguna (subjek). Berikut adalah struktur data yang dinormalisasi (meskipun saya telah menggunakan MongoDB). Anda perlu memberi tahu pengguna tertentu tentang perubahan. Jadi itu adalah pemberitahuan per pengguna .. artinya jika ada 100 pengguna yang terlibat, Anda menghasilkan 100 pemberitahuan.

Awalnya saya berpikir bahwa saya memahami pendekatan ini, tetapi ketika saya mulai bersiap untuk mengimplementasikannya, saya menyadari bahwa saya tampaknya tidak memahaminya dengan baik. Beberapa komentar terakhir tentang jawabannya adalah pertanyaan dari pengguna lain yang juga mengalami kesulitan dalam memahami solusinya.

Saya tidak yakin apakah ini model yang akan saya ikuti, tetapi mengingat jumlah upvote yang dimilikinya, saya yakin itu akan menguntungkan saya untuk memahaminya , dan saya pasti ingin belajar lebih banyak. Saya harap ini juga berguna bagi orang lain yang mengalami kesulitan dalam memahami solusi ini (kebetulan, saya tidak memiliki cukup poin internet untuk meninggalkan komentar pada jawaban yang mengarah ke pertanyaan ini, siapa pun tolong lakukan!)

Pertanyaan

Jika saya memahaminya dengan benar, notificationObjectID adalah kunci asing yang menunjuk ke tabel notification_object , dan notificationID adalah kunci asing yang menunjuk ke tabel notifikasi . Sepertinya objek harus berupa kunci asing yang merujuk ke ID dari entri basis data yang menjadi notifikasi (misalnya acara atau pos tertentu), tetapi bukankah kita memerlukan bidang lain untuk menunjukkan tabel yang menjadi milik ID?

Penulis menulis

notification_object.object mengidentifikasi tipe perubahan, seperti string "persahabatan" Referensi aktual untuk objek berubah dengan data ekstra yang saya bicarakan adalah di notification_change.notificationObjectID

yang tampaknya tidak masuk akal bagi saya. Objek adalah string (enum?) Dan notificationObjectID adalah kunci asing yang merujuk ke objek yang menjadi tujuan notifikasi? Lalu bagaimana tabel tengah dan kanan terhubung sama sekali?

Tampaknya tabel tengah menentukan objek apa (atau jenis objek) pemberitahuan tersebut, misalnya acara atau posting. Kami kemudian dapat memiliki banyak entri di notification_change yang mengarah ke jenis objek yang sama, yang memungkinkan kami untuk menggabungkan pemberitahuan (seperti "25 pengguna yang diposting di dinding X) - karenanya hubungan 1: n antara tabel tengah dan kanan.

Tetapi mengapa ada hubungan 1: n antara tabel kiri dan tengah? Apakah kita akan memberikan "25 pengguna yang diposting di dinding Sam" dan "Mary memperbarui acara" Piknik Jumat "nya dengan ID notifikasi yang sama? Jika semua notifikasi untuk pengguna yang sama memiliki ID notifikasi yang sama, mengapa kita bahkan memerlukan tabel di kiri?

Sebuah pertanyaan kinerja - katakanlah John memposting komentar tentang acara piknik Mary. Sepertinya kita perlu melakukan pencarian untuk melihat apakah notification_object sudah ada untuk Mary's Picnic sebelum kita membuat entri notification_change . Apakah ini akan berdampak negatif pada kinerja, atau itu bukan masalah? Melanjutkan pertanyaan dari paragraf sebelumnya, bagaimana kita tahu entri notifikasi mana untuk mengarahkan notification_object ?

pengguna45623
sumber

Jawaban:

8

Terima kasih untuk pertanyaan menyeluruh seperti itu, dan maaf untuk semua kebingungan - berkomentar 1 tahun setelah jawaban awal sulit dan sekarang 3 tahun setelah .. pemikiran awal memudar dan membingungkan saya juga, tapi saya takut untuk mengedit lubang karena saya tidak bekerja tentang menyimpan notifikasi di backend sekarang dan tidak yakin apakah saya membuat penilaian yang baik tanpa aplikasi praktis

Saya pikir pada saat penulisan:

  • Ya dan tidak, notificationID adalah kunci asing, notificationObjectID tidak. Anda perlu bidang FK lain untuk mengikat tabel bersama. Saya menyalahkan pengalaman mongo saya karena tidak begitu jelas tentang hal itu :(
  • Ya dan tidak, notification_object.object tidak jelas karena Anda dapat memilikinya hanya sebagai string, atau sesuatu yang kompleks (JSON, atau FK). Dalam kasus saya itu hanya kata benda.

Jadi itu semua tergantung pada bagaimana tampilan notifikasi Anda. Untuk kasus sederhana, Anda hanya ingin menautkan seluruh notifikasi ke beberapa URL, seperti halaman teman - itu sebabnya memiliki objek (entitasType) sebagai string berguna - Anda mengikat URL ke sana.

Pemberitahuan "Anda memiliki 3 permintaan pertemanan yang ditambahkan" dapat disimpan secara berbeda.

Jika Anda ingin menampilkannya satu per satu - Anda akan memiliki 3 notifikasi, 3 objek notifikasi (friend_request) dan 3 entri di notification_change yang menghubungkan ke pengguna teman tertentu.

Jika Anda ingin menampilkan satu pemberitahuan - Anda akan memiliki 1 pemberitahuan, 1 / lebih objek dan 3 / lebih tindakan. Jadi, dalam kasus rumit ini, seperti «Anda memiliki 3 permintaan teman dari pengguna A, pengguna B, pengguna C» - Anda menggunakan notificationObjectIDs untuk setiap pengguna dan memiliki beberapa tautan dalam teks pemberitahuan Anda.

Haruskah Anda menggunakan 1 atau 3 objek friend_request? Tergantung pada

  1. Apa objek dan apa tindakannya. Apakah «artikel disukai / dikomentari»? Atau apakah itu «suka / komentar ditambahkan» dan hierarki objek hanya ditautkan selama tampilan? Inilah Facebook yang membedakan «komentar foto» dari «menyebutkan pengguna» yang secara semantik tampak sangat dekat - Anda memiliki foto yang sama, aktor yang sama tetapi pemberitahuan berbeda yang dapat digabungkan bersama

masukkan deskripsi gambar di sini

  1. Bisakah Anda menghapus pemberitahuan atau perlu riwayat? Jadi jika saya mengirim permintaan pertemanan dan kemudian membatalkannya, atau berkomentar dan kemudian menghapus sebuah artikel, suka dan kemudian tidak seperti sesuatu - haruskah ini menunjukkan riwayat ini (sebagai tindakan lain) kepada pengguna akhir sebagai dua tindakan yang berbeda? Mungkin tidak. Selain itu secara teknis lebih kompleks - Anda perlu mencari jika ada notification_object yang ada, tambahkan notification_change baru untuk itu (jika tidak - tambahkan objek baru) sehingga nanti saya akan perlu mencari melalui notification_change untuk menghapusnya. Alih-alih, saya hanya akan menambahkan notification_object lain ke notifikasi yang sama dan menghapusnya jika itu pergi dengan tindakan semakin kaskade-dihapus.

Di sisi lain, mungkin ada kasus, di mana mungkin berguna untuk memiliki pengelompokan tindakan di mana tidak ada yang terhapus dari sejarah.

Saya pikir itulah sebabnya pada saat penulisan, hubungan 1: n antara tabel kiri dan tengah dilakukan - sehingga Anda dapat mengelompokkan notifikasi tidak hanya oleh aktor pada entitas yang sama (tabel kanan-tengah) tetapi oleh beberapa objek / entitas juga.

Tetapi tentu saja, Anda dapat menyederhanakan seluruh kasing dan mengoptimalkan penyimpanan dengan membalikkan hubungan tengah-kiri ke n: 1, sehingga Anda memiliki notifikasi per-pengguna yang dihasilkan untuk satu peristiwa.

Sehingga akan terlihat lebih seperti ini ..

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

Semoga ini bisa membantu

Artjom Kurapov
sumber
Hebat, terima kasih atas jawaban menyeluruh ini. Saya akan membahasnya dan memberi tahu Anda jika saya memiliki pertanyaan lain, tetapi saya pikir ini menjelaskan semuanya dengan sangat baik.
user45623