>用户将创建一个用户名,电子邮件和密码的帐户.该
电子邮件和密码可以随时更改.
>用户可以添加其他用户作为其联系人.用户将添加一个
通过搜索他们的用户名或电子邮件联系.联系人不需要
如果我添加一个他们是我的联系人的用户,那就是相互的意思,我不会
需要等待他们接受/批准像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)
阅读几本Cassandra教科书,我想到了如何建模数据库.我的主要关注点是以非常有效的方式对数据库进行建模.所以我试图避免二次索引等事情.这是迄今为止的模式:
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,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,[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];
干杯
解决方法
Cassandra的一些功能应该允许你这样做.
由于您是Cassandra的新手,您可能会使用目前处于测试版本的Cassandra 3.0.在3.0中有一个很好的功能,称为物化视图.这将允许您将users_by_username作为基表,并将users_by_email创建为实例化视图.那么当你更新基表时,Cassandra会自动更新视图.
帮助您的另一个功能是用户定义的类型(在C * 2.1及更高版本中).不必为关注者和消息创建单独的表,您可以创建UDT的结构,然后在用户表中保留这些类型的列表.
因此,您的模式的简化视图可能是这样的(我没有显示一些字段,如时间戳来保持这个简单,但是这些容易添加).
首先创建你的UDT的:
CREATE TYPE user_follows ( followed_username text,street text,); CREATE TYPE msg ( from_user text,body text );
接下来我们创建你的基表:
CREATE TABLE users_by_username ( username text PRIMARY KEY,password text,follows list<frozen<user_follows>>,followed_by list<frozen<user_follows>>,new_messages list<frozen<msg>>,old_messages list<frozen<msg>> );
现在我们创建一个通过电子邮件分区的物化视图:
CREATE MATERIALIZED VIEW users_by_email AS SELECT username,password,follows,new_messages,old_messages FROM users_by_username WHERE email IS NOT NULL AND password IS NOT NULL AND follows IS NOT NULL AND new_messages IS NOT NULL PRIMARY KEY (email,username);
现在让我们来看看它能做些什么.让我们创建一个用户:
INSERT INTO users_by_username (username,email,password ) VALUES ( 'someuser','someemail@abc.com','somepassword');
UPDATE users_by_username SET follows = [{followed_username: 'followme2',street: 'mystreet2'}] + follows WHERE username = 'someuser';
我们来给用户一个消息:
UPDATE users_by_username SET new_messages = [{from_user: 'auser',body: 'hi someuser!'}] + new_messages WHERE username = 'someuser';
现在看看表中有什么?
SELECT * FROM users_by_username ; username | email | followed_by | follows | new_messages | old_messages | password ----------+-------------------+-------------+---------------------------------------------------------+----------------------------------------------+--------------+-------------- someuser | someemail@abc.com | null | [{followed_username: 'followme2',street: 'mystreet2'}] | [{from_user: 'auser',body: 'hi someuser!'}] | null | somepassword
现在我们检查一下我们的物化视图是否正常工作:
SELECT new_messages,old_messages FROM users_by_email WHERE email='someemail@abc.com'; new_messages | old_messages ----------------------------------------------+-------------- [{from_user: 'auser',body: 'hi someuser!'}] | null
BEGIN BATCH DELETE new_messages[0] FROM users_by_username WHERE username='someuser' UPDATE users_by_username SET old_messages = [{from_user: 'auser',body: 'hi someuser!'}] + old_messages where username = 'someuser' APPLY BATCH; SELECT new_messages,old_messages FROM users_by_email WHERE email='someemail@abc.com'; new_messages | old_messages --------------+---------------------------------------------- null | [{from_user: 'auser',body: 'hi someuser!'}]
所以希望能给你一些可以使用的想法.看看集合文档(即列表,地图和集合),因为这些文档真的可以帮助您在一个表格中保留更多的信息,并且像表格中的表格一样.