Cassandra Datenmodell für einfache Messaging-App

Ich versuche Cassandra zu lernen und finde immer, dass es am besten ist, eine sehr einfache und kleine Anwendung zu erstellen. Daher erstelle ich eine grundlegende Messaging-Anwendung, die Cassandra als Backend verwendet. Ich würde gerne folgendes machen:

User erstellt ein Konto mit einem Benutzernamen, einer E-Mail-Adresse und einem Passwort. Die E-Mail-Adresse und das Passwort können jederzeit geändert werden.Der Benutzer kann einen anderen Benutzer als Kontakt hinzufügen. Der Benutzer würde einen Kontakt hinzufügen, indem er seinen Benutzernamen oder seine E-Mail-Adresse durchsucht. Die Kontakte müssen keine gegenseitige Bedeutung haben, wenn ich einen Benutzer hinzufüge, der mein Kontakt ist. Ich muss nicht warten, bis sie etwas wie in Facebook akzeptieren / genehmigen.Eine Nachricht wird von einem Benutzer an einen anderen Benutzer gesendet. Der Absender muss in der Lage sein, die von ihm gesendeten (nach Zeit geordneten) Nachrichten und die an ihn gesendeten (nach Zeit geordneten) Nachrichten anzuzeigen. Wenn ein Benutzer die App öffnet, muss ich die Datenbank auf neue Nachrichten für diesen Benutzer überprüfen. Ich muss auch markieren, ob die Nachricht gelesen wurde.

Als ich aus der Welt der relationalen Datenbanken komme, würde meine relationale Datenbank ungefähr so aussehen:

UsersTable
    username (text)
    email (text)
    password (text)
    time_created (timestamp)
    last_loggedIn (timestamp)
------------------------------------------------ 
ContactsTable
    user_i_added (text)
    user_added_me (text)
------------------------------------------------     
MessagesTable
    from_user (text)
    to_user (text)
    msg_body (text)
    metadata (text)
    has_been_read (boolean)
    message_sent_time (timestamp)

In ein paar Cassandra-Lehrbüchern habe ich darüber nachgedacht, wie man die Datenbank modelliert. Mein Hauptanliegen ist es, die Datenbank auf sehr effiziente Weise zu modellieren. Daher versuche ich, Dinge wie Sekundärindizes usw. zu vermeiden. Dies ist bisher mein Modell:

CREATE TABLE users_by_username (
    username text PRIMARY KEY,
    email text,
    password text
    timeCreated timestamp
    last_loggedin timestamp
)

CREATE TABLE users_by_email (
    email text PRIMARY KEY,
    username text,
    password text
    timeCreated timestamp
    last_loggedin timestamp
)

Um Daten gleichmäßig zu verteilen und eine minimale Anzahl von Partitionen (hoffentlich nur eine) zu lesen, kann ich einen Benutzer anhand seines Benutzernamens oder seiner E-Mail-Adresse schnell suchen. Der Nachteil dabei ist natürlich, dass ich meine Daten verdopple, aber die Kosten für die Speicherung sind recht günstig, und ich finde, dass dies ein guter Kompromiss ist, anstatt Sekundärindizes zu verwenden. Das zuletzt angemeldete muss auch zweimal geschrieben werden, aber Cassandra kann sehr gut schreiben. Ich glaube, das ist auch ein guter Kompromiss.

Für die Kontakte kann ich mir keine andere Möglichkeit vorstellen, dies zu modellieren. Daher habe ich es sehr ähnlich modelliert wie in einer relationalen Datenbank. Dies ist ein ziemlich denormalisiertes Design, von dem ich glaube, dass es laut den Büchern, die ich gelesen habe, gut für die Leistung sein sollt

CREATE TABLE "user_follows" (
  follower_username text,
  followed_username text,
  timeCreated timestamp, 
  PRIMARY KEY ("follower_username", "followed_username")
);

CREATE TABLE "user_followedBy" (

  followed_username text,
  follower_username text,
  timeCreated timestamp,
  PRIMARY KEY ("followed_username", "follower_username")
);

Ich bin nicht sicher, wie ich dieses nächste Teil erstellen soll. Beim Versenden von Nachrichten habe ich an diese Tabelle gedacht, da sie breite Zeilen erstellt, die die Reihenfolge der Nachrichten ermöglichen. Ich benötige Nachrichten, um zwei Fragen zu beantworten. Zunächst muss es dem Benutzer alle Nachrichten anzeigen können, die er hat, und es muss dem Benutzer auch die Nachrichten anzeigen können, die neu und ungelesen sind. Dies ist ein Basismodell, aber Sie sind sich nicht sicher, wie Sie es effizienter gestalten können?

CREATE TABLE messages (
    message_id uuid,
    from_user text,
    to_user text,
    body text,
    hasRead boolean,
    timeCreated timeuuid,
    PRIMARY KEY ((to_user), timeCreated )
) WITH CLUSTERING ORDER BY (timeCreated ASC);

Ich habe auch versucht, mithilfe von STATIC-Spalten Benutzer und Nachrichten zusammenzufügen und SETS zum Speichern von Kontaktbeziehungen zu verwenden. Aufgrund meines engen Verständnisses ist meine Darstellung jedoch effizienter. Ich frage, ob es irgendwelche Ideen gibt, um die Effizienz dieses Modells zu verbessern, ob es bessere Praktiken gibt, um die Dinge zu tun, die ich versuche, oder ob es irgendwelche versteckten Probleme gibt, denen ich mit diesem Design begegnen kan

Abschließend versuche ich, die Abfragen zu modellieren. Wenn ich Beziehungsdatenbanken verwenden würde, wären dies im Wesentlichen die Fragen, die ich beantworten möchte:

To Login:
SELECT * FROM USERS WHERE (USERNAME = [MY_USERNAME] OR EMAIL = [MY_EMAIL]) AND PASSWORD = [MY_PASSWORD];
------------------------------------------------------------------------------------------------------------------------
Update user info:
UPDATE USERS (password) SET password = [NEW_PASSWORD] where username = [MY_USERNAME];
UPDATE USERS (email) SET password = [NEW_PASSWORD ] where username = [MY_USERNAME];
------------------------------------------------------------------------------------------------------------------------ 
To Add contact (If by username):
INSERT INTO followings(following,follower)  VALUES([USERNAME_I_WANT_TO_FOLLOW],[MY_USERNAME]);
------------------------------------------------------------------------------------------------------------------------
To Add contact (If by email):
SELECT username FROM users where email = [CONTACTS_EMAIL];
    Then application layer sends over another query with the username:
INSERT INTO followings(following,follower)  VALUES([USERNAME_I_WANT_TO_FOLLOW],[MY_USERNAME]);
------------------------------------------------------------------------------------------------------------------------
To View contacts:
SELECT following FROM USERS WHERE follower = [MY_USERNAME];
------------------------------------------------------------------------------------------------------------------------
To Send Message:,
INSERT INTO MESSAGES (MSG_ID, FROM, TO, MSG, IS_MSG_NEW) VALUES (uuid, [FROM_USERNAME], [TO_USERNAME], 'MY MSG', true);
------------------------------------------------------------------------------------------------------------------------
To View All Messages (Some pagination type of technique where shows me the 10 recent messages, yet shows which ones are unread):
SELECT * FROM MESSAGES WHERE TO = [MY_USERNAME] LIMIT 10;
------------------------------------------------------------------------------------------------------------------------
Once Message is read:
UPDATE MESSAGES SET IS_MSG_NEW = false WHERE TO = [MY_USERNAME] AND MSG_ID = [MSG_ID];

Pros

Antworten auf die Frage(4)

Ihre Antwort auf die Frage