我想学习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
)
要均匀地分布数据和读取分区的最小量(希望只有一个)我可以查找基于用户快速输入用户名或电子邮件这样做的缺点显然是我的数据翻倍,但是存储成本相当便宜,所以我觉得这是一个很好的折衷,而不是使用二级索引。上次登录也需要两次写入,但Cassandra在写入时非常有效,所以我相信这是一个很好的折衷方案。
对于联系人,我想不出任何其他方式来模拟这个模型,所以我将它与我在关系数据库中的模型非常类似。这是相当不规范的设计,我相信,根据我读过的书籍,这应该对性能有好处?
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")
);
我被困在如何创建下一部分。对于消息传递,我正在考虑这张表,因为它创建了宽行,从而可以对消息进行排序。 我需要消息来回答两个问题。它首先需要能够向用户显示他们拥有的所有消息,并且能够向用户显示新消息并且未读的消息 。这是一个基本模型,但我不确定如何使它更有效率?
我也考虑使用的东西,比如静态列“粘”在一起,用户和消息,以及设置为存储联系人的关系,但是从我的狭隘理解到目前为止,我所呈现的方式是更高效。我问是否有任何想法可以改善这种模式的效率,如果有更好的做法做我正在尝试做的事情,或者如果我可以用这种设计来解决任何隐藏的问题?
总之,我试图对查询进行建模。如果我使用关系数据库,这些将基本上是我期待的查询回答:
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];
干杯