微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

数据库 – 用于简单消息应用的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)

阅读几本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加盟的奢侈品,那么你经常想要尽可能多地填入一张桌子.在你的情况下,这将是users_by_username表.

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!'}]

所以希望能给你一些可以使用的想法.看看集合文档(即列表,地图和集合),因为这些文档真的可以帮助您在一个表格中保留更多的信息,并且像表格中的表格一样.

原文地址:https://www.jb51.cc/mssql/82946.html

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐