Ludzie uwielbiają się komunikować. Często żartujemy, że każdy system oprogramowania zawsze ewoluuje w system przesyłania wiadomości. W tym artykule wyjaśniono wymagania systemowe i krok po kroku podejście do projektowania modelu danych dla systemu przesyłania wiadomości.
Wymagania w skrócie
Podstawową funkcją systemu przesyłania wiadomości w aplikacji jest wysyłanie powiadomień/wiadomości do użytkownika lub zbioru użytkowników. Nasz system umożliwia również wysyłanie wiadomości do grupy użytkowników. Grupy użytkowników można oczywiście tworzyć na podstawie niektórych parametrów, takich jak uprawnienia dostępu, położenie geograficzne użytkowników itp.
Ten system umożliwia odbiorcom odpowiedź do wiadomości. Śledzi również, kto przeczytał wiadomość, a kto nie.
Ponadto system ma wbudowane przypomnienie mechanizm, który pozwala nadawcy stworzyć przypomnienie, a następnie odpowiednio wysłać przypomnienie do wszystkich odbiorców.
Podmioty i relacje
W tym modelu danych user
i message
są głównymi podmiotami przechowującymi dane użytkowników i wiadomości.
Kolumny w user
tabela byłaby atrybutami związanymi z użytkownikiem, takimi jak first_name
, last_name
itp.
Niektóre oczywiste kolumny w message
tabela byłaby subject
, message_body
, create_date
i expiry_date
. Dodaję również kolumnę klucza obcego o nazwie creator_id
w tej tabeli, która odwołuje się do id
kolumna user
stół. Jak sama nazwa wskazuje, oznacza id twórcy wiadomości. Ponieważ dla wiadomości zawsze będzie jeden twórca, zachowuję tę kolumnę tylko w tabeli wiadomości. Być może zastanawiasz się, dlaczego istnieje expiry_date
kolumna w tabeli. Dodałem tę kolumnę, aby zarządzać przypomnieniami w wiadomościach. Więcej na temat tej kolumny wyjaśnię w dalszej części tego artykułu.
Najważniejszą tabelą w tym modelu danych jest message_recipient
. Powiedziałbym, że cały model danych kręci się tylko wokół tej tabeli. Jednym z głównych celów tworzenia tej tabeli jest odwzorowanie wiadomości i ich odbiorców. Zatem recipient_id
kolumna w tej tabeli oznacza identyfikatory odbiorców, a ta kolumna odnosi się do kolumny identyfikatora user
tabela.
Gdy wiadomość zostanie wysłana do jednego odbiorcy, do tej tabeli zostanie wstawiony jeden rekord z identyfikatorem odbiorcy w recipient_id
kolumna.
Teraz możesz się zastanawiać, jaki jest recipient_group_id
kolumna oznacza w tej tabeli. W tym miejscu powinienem najpierw wyjaśnić, w jaki sposób ten model można rozszerzyć o wymóg wysyłania wiadomości do wielu odbiorców jednocześnie.
Wysyłanie wiadomości do grupy
Potrzebuję innej tabeli, a mianowicie group
, aby przechowywać szczegóły grupy. Ponieważ istnieje relacja wiele-do-wielu między user
i group
tabele, czyli użytkownik może należeć do więcej niż jednej grupy, utworzę kolejną tabelę o nazwie user_group
.
Na przykład, jeśli grupa jest utworzona z 25 użytkownikami, w user_group
tabela.
Wróćmy do message_recipient
stół. Dodaję odwołanie do klucza podstawowego user_group
tabeli do message_recipient
stół. Nazywam go recipient_group_id
. Ta kolumna będzie zawierać wartość grupy użytkowników, dla której wiadomość jest wysłana.
Teraz za każdym razem, gdy wiadomość jest wysyłana do grupy, wiele rekordów zostanie wstawionych do message_recipient
tabela na podstawie liczby użytkowników w grupie i recipient_group_id
zostaną odpowiednio zarejestrowane we wszystkich tych rekordach.
Pozwólcie, że zilustruję to dalej przykładem. Załóżmy, że wiadomość została wysłana do grupy 10 osób. W tym przypadku łącznie 10 rekordów, po jednym dla każdego recipient_group_id
grupy, zostanie wstawiony do message_recipient
tabela.
Pamiętaj, że jeśli wiadomość jest wysyłana do użytkownika, a nie do grupy, to recipient_group_id
kolumna pozostaje pusta. W tym przypadku bezpośredni user_id
zostanie zarejestrowany pod recipient_id
kolumna.
Dodam jeszcze jedną kolumnę o nazwie is_read
do tabeli, aby umieścić flagę przy użytkowniku wiadomości, która wskazuje, czy wiadomość jest czytana przez użytkownika.
Unikalny klucz message_recipient
tabela – powinien znajdować się unikalny klucz złożony w kolumnach message_id
, recipient_id
i recipient_group_id
, aby zapewnić, że istnieje tylko jeden rekord dla unikalnej kombinacji tych kolumn.
Zachowuję is_active
kolumnę we wszystkich tabelach z wyjątkiem message i message_recipient, aby umożliwić „miękkie usuwanie” rekordów. Ponieważ dodałem expiry_date
kolumna w tabeli wiadomości, is_active
kolumna nie jest potrzebna. Co więcej, ta kolumna nie jest potrzebna w message_recipient
tabeli, ponieważ wiadomości nie można cofnąć bezpośrednio po jej wysłaniu. Można go jednak dezaktywować, aktualizując expiry_date
dla wiadomości z datą z przeszłości.
Odpowiadanie na wiadomość
Załóżmy teraz, że system pozwala użytkownikom odpowiadać na otrzymane wiadomości. Rozszerzam tę samą tabelę message
aby spełnić ten wymóg, zamiast tworzyć nową tabelę odpowiedzi. Dodam jedną kolumnę o nazwie parent_message_id
aby ustanowić hierarchiczną relację między wiadomościami. Wstawię nowy rekord do wiadomości zwrotnej i zaktualizuję parent_message_id
kolumna na wiadomości zwrotne. Model ten obsługuje n-poziomową relację hierarchiczną, tj. odpowiedź na wiadomość zwrotną może być również śledzona za pomocą tego modelu.
Panel do przeglądania „odczytu %” każdej wiadomości
is_read
flaga jest rejestrowana dla każdego rekordu użytkownika wiadomości. Wartość tej flagi pozostaje ZERO, dopóki wiadomość nie zostanie odczytana przez użytkownika. Zostanie zaktualizowany do JEDNEGO, gdy tylko wiadomość zostanie przeczytana przez użytkownika. Na podstawie wartości kolumny można określić „% odczytu” wiadomości wysyłanej do grupy.
Napiszę przykładowy kod SQL, aby pobrać taki raport:
SELECT msg.subject, sent_to, msg.create_date, (summ / countt) * 100 AS Read_Per FROM (SELECT msg.subject, grp.name as sent_to, msg.create_date, SUM (is_read) AS summ, COUNT (is_read) AS countt FROM message_recipient msgrec, message msg, user_group ug, group grp WHERE msgrec.message_id = msg.id AND msgrec.recipient_group_id = ug.id AND ug.GROUP_ID = grp.id AND msgrec.recipient_group_id IS NOT NULL GROUP BY msg.subject, grp.name, msg.create_date UNION SELECT msg.subject, u.first_name || ' ' || u.last_name as sent_to, msg.create_date, SUM (is_read) AS summ, COUNT (is_read) AS countt FROM message_recipient msgrec, MESSAGE msg, user u WHERE msgrec.message_id = msg.id AND msgrec.recipient_id = u.id AND msgrec.recipient_group_id IS NULL GROUP BY msg.subject, name, msg.create_date);
Temat | Wysłano do | Wysłane | Czytaj % |
---|---|---|---|
Dostarczenie projektu we wtorek | Zespół realizujący projekt | 13.09.2015 08:15 | 42% |
Spotkajmy się w poniedziałek | Jan D | 10.09.2015 13:30 | 100% |
Zsynchronizuj środowisko deweloperskie z produkcją | zespół DBA | 09.09.2015 09:11 | 80% |
Zamykanie NCR audytu | Zespół NSS | 09.09.2015 17:50 | 45% |
Mechanizm przypominania
Dla przypomnienia dodam następujące kolumny w tabeli wiadomości:
Is_reminder
– Ta kolumna wskazuje, czy dla wiadomości wymagane jest przypomnienie.Reminder_frequency_id
– Ta kolumna oznacza częstotliwość przypominania. Czy powinno to odbywać się codziennie czy co tydzień?Next_remind_date
– W tej kolumnie znajduje się data, kiedy należy wysłać następne przypomnienie. Przypomnienie zostanie wysłanenext_remind_date
dla użytkowników, dla których flaga „is_read” wynosi jeszcze ZERO. Nowa wartość dla tej kolumny zostanie obliczona za każdym razem, gdy zostanie wysłane przypomnienie.Expiry_date
– Ta kolumna to data graniczna, kiedy przypomnienia nie będą już wysyłane do użytkowników.
Obliczanie next_remind_date
wyglądałoby następująco – Załóżmy, że jedna wiadomość zostanie wysłana do użytkowników 14 września w poniedziałek z datą wygaśnięcia 10/5. Wiadomość jest wysyłana z tygodniową częstotliwością przypomnień. W takim przypadku przypomnienia zostaną wysłane do użytkowników 21 września i 28 września, aby odpowiedzieć na nie e-mailem, a ostatni raz 5 października, aby zachęcić ich do odpowiedzi w ciągu najbliższych 24 godzin.
Końcowy model danych
Wniosek
Jednym z najlepszych zastosowań tego systemu przesyłania wiadomości jest wysyłanie powiadomień do użytkowników, którzy byli nieaktywni w systemie przez długi czas. Powiadomienia te mogą być wysyłane z włączonym mechanizmem przypominania, a powiadomienia będą wysyłane do użytkowników, dopóki użytkownicy nie odpowiedzą na powiadomienie. Użytkownicy zostaną dezaktywowani w dniu i po dacie wygaśnięcia, jeśli nie otrzymają od nich odpowiedzi na powiadomienia.
Zamierzałem zbudować model danych dla w pełni funkcjonalnego systemu przesyłania wiadomości, który można dopasować do różnych systemów do wysyłania wiadomości/powiadomień. Zapraszam do dzielenia się swoimi poglądami/wkładami/komentarzami do artykułu.