Modelo de dados Cassandra para aplicativo de mensagens simples

Estou tentando aprender o Cassandra e sempre encontro a melhor maneira de começar criando uma aplicação muito simples e pequena. Portanto, estou criando um aplicativo básico de mensagens que usará o Cassandra como back-end. Eu gostaria de fazer o seguinte:

O usuário criará uma conta com um nome de usuário, email e senha. O email e a senha podem ser alterados a qualquer momento.O usuário pode adicionar outro usuário como contato. O usuário adicionaria um contato pesquisando seu nome de usuário ou email. Os contatos não precisam ter significado mútuo se eu adicionar um usuário, ele é meu contato, não preciso esperar que ele aceite / aprove algo como no Facebook.Uma mensagem é enviada de um usuário para outro usuário. O remetente precisa poder ver as mensagens enviadas (ordenadas por hora) e as mensagens que foram enviadas a elas (ordenadas por hora). Quando um usuário abre o aplicativo, preciso verificar se há novas mensagens no banco de dados. Também preciso marcar se a mensagem foi lida.

Como eu venho do mundo dos bancos de dados relacionais, meu banco de dados relacional seria algo assim:

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)

Lendo alguns livros didáticos de Cassandra, pensei em como modelar o banco de dados. Minha principal preocupação é modelar o banco de dados de maneira muito eficiente. Por isso, estou tentando evitar coisas como índices secundários etc. Este é o meu modelo até agora:

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
)

Para espalhar os dados uniformemente e ler uma quantidade mínima de partições (espero apenas uma), posso procurar um usuário com base em seu nome de usuário ou email rapidamente. A desvantagem disso é obviamente que estou dobrando meus dados, mas o custo de armazenamento é bastante barato, portanto, acho que é uma boa opção em vez de usar índices secundários. O último login também precisará ser gravado duas vezes, mas o Cassandra é eficiente na gravação, então acredito que essa seja uma boa alternativa.

Para os contatos, não consigo pensar em outra maneira de modelar isso, então modelei-o de maneira muito semelhante a como faria em um banco de dados relacional. Acredito que esse é um design desnormalizado que deve ser bom para o desempenho, de acordo com os livros que li?

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")
);

Estou preso em como criar esta próxima parte. Para as mensagens, eu estava pensando nesta tabela, pois ela cria linhas largas que permitem a ordenação das mensagens. Preciso de mensagens para responder a duas perguntas. Primeiro, ele deve poder mostrar ao usuário todas as mensagens que ele possui e também mostrar ao usuário as mensagens que são novas e que não foram lidas. Este é um modelo básico, mas não tenho certeza de como torná-lo mais eficaz?

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);

Eu também estava olhando para usar coisas como colunas STATIC para 'colar' o usuário e as mensagens, bem como o SETS para armazenar relacionamentos de contato, mas pelo meu entendimento restrito até agora, a maneira como apresentei é mais eficiente. Pergunto se há alguma idéia para melhorar a eficiência desse modelo, se existem práticas melhores que as coisas que estou tentando fazer ou se há algum problema oculto que eu possa enfrentar com esse design.

Em conclusão, estou tentando modelar as consultas. Se eu estivesse usando bancos de dados de relações, essas seriam essencialmente as consultas que pretendo responder:

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];

Felicidades

questionAnswers(2)

yourAnswerToTheQuestion