Модель данных Cassandra для простого приложения обмена сообщениями
Я пытаюсь выучить Cassandra и всегда нахожу лучший способ начать с создания очень простого и небольшого приложения. Поэтому я создаю базовое приложение для обмена сообщениями, которое будет использовать Cassandra в качестве серверной части. Я хотел бы сделать следующее:
Пользователь создаст учетную запись с именем пользователя, электронной почтой и паролем. Электронная почта и пароль могут быть изменены в любое время.Пользователь может добавить другого пользователя в качестве своего контакта. Пользователь может добавить контакт, выполнив поиск по имени пользователя или электронной почте. Контакты не должны быть взаимно значимыми, если я добавляю пользователя, он является моим контактом, мне не нужно ждать, пока они примут / одобрят что-либо подобное в Facebook.Сообщение отправляется от одного пользователя другому пользователю. Отправитель должен иметь возможность видеть отправленные им сообщения (упорядоченные по времени) и отправленные им сообщения (упорядоченные по времени). Когда пользователь открывает приложение, мне нужно проверить базу данных на наличие новых сообщений для этого пользователя. Мне также нужно отметить, если сообщение было прочитано.Поскольку я родом из мира реляционных баз данных, моя реляционная база данных будет выглядеть примерно так:
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)
Прочитав пару учебников Кассандры, я подумал о том, как смоделировать базу данных. Моя главная задача - очень эффективно смоделировать базу данных. Поэтому я стараюсь избегать таких вещей, как вторичные индексы и т. Д. Это моя модель до сих пор:
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
)
Чтобы распределить данные равномерно и прочитать минимальное количество разделов (возможно, только один), я могу быстро найти пользователя по его имени или электронной почте. Недостатком этого является то, что я удваиваю свои данные, но стоимость хранилища довольно дешевая, поэтому я считаю, что это хороший компромисс вместо использования вторичных индексов. Последний вход в систему также должен быть записан дважды, но Кассандра эффективна при записи, поэтому я считаю, что это также хороший компромисс.
Что касается контактов, я не могу придумать какой-либо другой способ смоделировать это, поэтому я смоделировал это очень похоже на то, как в реляционной базе данных. Я считаю, что это довольно денормализованный дизайн, который должен быть хорош для работы в соответствии с книгами, которые я прочитал?
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")
);
Я застрял на том, как создать эту следующую часть. Для обмена сообщениями я думал об этой таблице, так как она создавала широкие строки, позволяющие упорядочивать сообщения. Мне нужно сообщение, чтобы ответить на два вопроса. Сначала необходимо уметь показывать пользователю все имеющиеся у него сообщения, а также уметь показывать пользователю сообщения, которые являются новыми и непрочитанными. Это базовая модель, но я не уверен, как сделать ее более эффективной?
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);
Я также смотрел на использование таких вещей, как столбцы STATIC, чтобы «склеить» пользователя и сообщения, а также SETS для хранения отношений контактов, но из моего узкого понимания пока способ, которым я представил, более эффективен. Я спрашиваю, есть ли какие-нибудь идеи по повышению эффективности этой модели, если есть лучшие практики, которые я пытаюсь сделать, или есть какие-то скрытые проблемы, с которыми я могу столкнуться с этим дизайном?
В заключение я пытаюсь смоделировать запросы. Если бы я использовал реляционные базы данных, это были бы запросы, на которые я хотел бы ответить:
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];
ура