Zrozumienie systemu powiadomień

15

Zastanawiałem się, jak zbudować system powiadomień na SE i gdzie indziej i znalazłem pociąg do rozwiązania, które jest akceptowaną odpowiedzią tutaj: /programming/9735578/building-a-notification-system, który używa ta struktura:

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

Powiadomienie dotyczy zmiany (obiektu = zdarzenia, przyjaźni ...) przez kogoś (aktora) i zgłoszenia go użytkownikowi (podmiotowi). Oto znormalizowana struktura danych (chociaż korzystałem z MongoDB). Musisz powiadomić niektórych użytkowników o zmianach. Tak więc są to powiadomienia dla poszczególnych użytkowników .. co oznacza, że ​​jeśli w grę wchodzi 100 użytkowników, generujesz 100 powiadomień.

Na początku myślałem, że zrozumiałem to podejście, ale kiedy zacząłem przygotowywać się do jego wdrożenia, zdałem sobie sprawę, że najwyraźniej nie rozumiem go szczególnie dobrze. Ostatnie kilka komentarzy do odpowiedzi to pytania innych użytkowników, którzy również mieli problemy ze zrozumieniem rozwiązania.

Nie jestem pewien, czy to model, za którym skończę, ale biorąc pod uwagę liczbę pozytywnych opinii, jestem pewien, że zrozumiałoby to go , a na pewno chciałbym dowiedzieć się więcej. Mam nadzieję, że przyda się to także innym, którzy mieli problem z uchwyceniem tego rozwiązania (nawiasem mówiąc, nie mam wystarczającej liczby punktów internetowych, aby skomentować tę odpowiedź kierując do tego pytania, proszę o to inne osoby!)

pytania

Jeśli dobrze to rozumiem, powiadomienieObjectID to klucz obcy wskazujący na tabelę powiadomienia_obiekt , a identyfikator powiadomienia to klucz obcy wskazujący na tabelę powiadomień . Wygląda jak przedmiot powinien być kluczem obcym odnoszącym się do identyfikatora wpisu bazy danych, którego dotyczy powiadomienie (np. Określone zdarzenie lub post), ale czy nie potrzebujemy wtedy innego pola wskazującego, do której tabeli należy ten identyfikator?

Autor napisał

notice_object.object identyfikuje typ zmiany, np. ciąg „przyjaźń” Rzeczywiste odniesienie do zmienionego obiektu z jego dodatkowymi danymi, o których mówię, znajduje się w powiadomienia_change.notificationObjectID

co nie wydaje mi się mieć sensu. Obiekt jest ciągiem znaków (enum?), A identyfikatorObiektuObjectID to klucz obcy odnoszący się do obiektu, o którym jest powiadomienie? Jak w ogóle są połączone środkowe i prawe stoły?

Wygląda na to, że środkowa tabela określa, o jakim obiekcie (lub typie obiektu) chodzi o powiadomienie, np. Zdarzenie lub post. Możemy wtedy mieć wiele wpisów w powiadomienia_zmiany, które wskazują na ten sam typ obiektu, co pozwala nam grupować powiadomienia (np. „25 użytkowników opublikowanych na ścianie X) - stąd relacja 1: n między środkową i prawą tabelą.

Ale dlaczego istnieje związek 1: n między lewym a środkowym stołem? Czy nadamy „25 użytkownikom umieszczonym na ścianie Sama” i „Mary zaktualizowała swoje wydarzenie„ Piątek piknik ”ten sam identyfikator powiadomienia? Jeśli wszystkie powiadomienia dla tego samego użytkownika mają ten sam identyfikator powiadomienia, dlaczego potrzebujemy tabeli lewo?

Pytanie o wydajność - powiedzmy, że John komentuje piknik Mary. Wygląda na to, że musielibyśmy sprawdzić, czy obiekt powiadomień istnieje już dla Mary's Picnic, zanim utworzymy wpis powiadomienia_zmiany . Czy wpłynie to negatywnie na wydajność, czy może nie będzie problemu? Kontynuując pytania z poprzedniego akapitu, skąd mielibyśmy wiedzieć, do którego powiadomienia należy skierować obiekt_zadania ?

użytkownik45623
źródło

Odpowiedzi:

8

Dziękuję za tak dokładne pytania i przepraszam za całe zamieszanie - komentowanie 1 rok po wstępnej odpowiedzi jest trudne, a teraz 3 lata po ... początkowe myśli znikają i mylą mnie, ale boję się edytować dziurę, ponieważ nie pracuję w sprawie przechowywania powiadomień na zapleczu w tej chwili i nie jestem pewien, czy dokonam dobrego osądu bez praktycznego zastosowania

Myślę, że w momencie pisania:

  • Tak i nie, identyfikator powiadomienia to klucz obcy, identyfikator powiadomienia nie był. Potrzebujesz innego pola FK, aby powiązać tabele. Obwiniam moje doświadczenie mongo, że nie jestem tak jasny :(
  • Tak i nie, powiadomienie_object.object jest niejasne, ponieważ możesz mieć go jako ciąg lub coś złożonego (JSON lub FK). W moim przypadku był to tylko rzeczownik.

Wszystko zależy więc od wyglądu powiadomień. W prostym przypadku chcesz po prostu połączyć całe powiadomienie z jakimś adresem URL, takim jak strona znajomych - dlatego przydatny jest obiekt (entityType) jako ciąg znaków - wiążesz z nim adresy URL.

Powiadomienie „ dodano 3 zaproszenia do znajomych ” może być przechowywane inaczej.

Jeśli chcesz je wyświetlać pojedynczo - będziesz mieć 3 powiadomienia, 3 obiekty powiadomień (żądanie_znajomego) i 3 wpisy w_wiadomości, które prowadzą do określonego użytkownika znajomego.

Jeśli chcesz pokazać jedno powiadomienie - będziesz mieć 1 powiadomienie, 1 / więcej obiektów i 3 / więcej akcji. Tak więc w tym złożonym przypadku, np. „Masz 3 prośby o dodanie do znajomych od użytkownika A, użytkownika B, użytkownika C” - dla każdego użytkownika korzystasz z powiadomieniaObjectID i masz kilka linków w tekście powiadomienia.

Czy powinieneś użyć 1 lub 3 obiektów friend_request? To zależy od

  1. Czym jest przedmiot i jaka jest akcja. Czy «artykuł jest lubiany / komentowany»? A może jest to „jak / komentarz dodany”, a hierarchia obiektów jest łączona tylko podczas wyświetlania? Oto facebook odróżniający „komentowanie zdjęć” od „wzmianki użytkownika”, które semantycznie wydają się być bardzo bliskie - masz to samo zdjęcie, tego samego aktora, ale różne powiadomienia, które mogły zostać połączone

wprowadź opis zdjęcia tutaj

  1. Czy możesz usunąć powiadomienie lub potrzebujesz historii? Więc jeśli wyślę prośbę do znajomego, a następnie ją anuluję lub skomentuję, a następnie usuń artykuł, polub, a następnie coś w przeciwieństwie do czegoś - czy powinien pokazywać tę historię (jako inną akcję) użytkownikowi końcowemu jako dwie różne akcje? Prawdopodobnie nie. Oprócz tego jest technicznie bardziej złożony - musisz wyszukać, czy istnieje już obiekt_zadania, dodaj do niego nowy parametr_zmiany (jeśli nie - dodaj nowy obiekt), aby później musiałem przeszukać przez opcję_zamówienia, aby go usunąć. Zamiast tego po prostu dodam kolejny obiekt_zadania do tego samego powiadomienia i usunę go, jeśli zniknie wraz z działaniami usuwanymi kaskadowo.

Z drugiej strony mogą zdarzyć się przypadki, w których przydatne może być grupowanie działań, w których nic nie zostaje usunięte z historii.

Myślę, że właśnie dlatego w momencie pisania została wykonana relacja 1: n między lewą a środkową tabelą - aby można było grupować powiadomienia nie tylko przez aktorów o tej samej encji (tabele środkowo-prawe), ale także przez kilka obiektów / encji.

Ale na pewno możesz uprościć całą sprawę i zoptymalizować pamięć, odwracając relację lewy-środkowy do n: 1, dzięki czemu dla jednego zdarzenia wygenerowane zostaną powiadomienia dla poszczególnych użytkowników.

Aby wyglądało to bardziej tak ...

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

Mam nadzieję, że to pomogło

Artjom Kurapov
źródło
Świetnie, dziękuję za tę dokładną odpowiedź. Przejdę przez to i dam ci znać, jeśli będę miał więcej pytań, ale myślę, że to wyjaśnia wszystko bardzo dobrze.
user45623