使用Cassandra的内部网络应用程序数据模型

时间:2019-07-02 23:32:18

标签: cassandra datamodel

我正在设计一个应用程序,它将使用户能够发送彼此连接的请求,查看他们的已发送或已接收的请求,在交互过程中做记录以供以后参考(如果已连接)以及将用户从其联系人列表中删除。

在RDBMS中,架构为:

具有列

的表用户
  • uid(每个用户的唯一字符串)

带有列的表请求:

  • 来自-用户ID

  • 至-用户ID主键(从,至)

  • 已创建-时间戳

  • 消息-字符串

  • 到期-时间戳

表与列的连接:

  • 来自-用户ID

  • 至-用户ID

主键(从,到)

  • 注释-字符串

  • 已创建-时间戳

  • 已修改-时间戳

  • isFavourite-to是用户的最爱,值为0或1

  • isActive-软删除,值为0或1

  • pairedConnection-显示是否取消了to与from之间的连接(to用户从其联系人列表中删除了from用户)

我期望需要的查询是:

  • 为用户找到发送的请求

  • 找到收到的用户请求

  • 查找给定用户的所有活动联系人

  • 找到用户的所有收藏夹

  • 找到所有从列表中删除用户的用户

  • 在遇到与他有联系的另一个用户时更新用户记录的笔记

  • 将用户更新为收藏夹

  • 标记连接以进行软删除

我正在尝试在Cassandra中对此建模,但是对于选择最大化效率的关键感到困惑。

到目前为止,我有以下想法,欢迎有经验的Cassandra用户提供反馈:

create table users(
uid text PRIMARY KEY
); 

create table requestsByFrom(
from text,
to text,
message text,
created timestamp,
expiry timestamp,
PRIMARY KEY (from,to)

create table requestsByTo(
from text,
to text,
message text,
created timestamp,
expiry timestamp,
PRIMARY KEY (to,from)
);

create table connections(
from text,
to text,
notes text,
created timestamp,
modified timestamp,
isFavourite boolean,
isActive boolean,
pairedConnection boolean,
PRIMARY KEY (from,to)
);

create table activeConnections(
from text,
to text,
isActive boolean,
PRIMARY KEY (from,isActive)
);

create table favouriteConnections(
from text,
to text,
isFavourite boolean,
PRIMARY KEY (from, isFavourite)
);

create table pairedConnection(
from text,
to text,
pairedConnection boolean,
PRIMARY KEY ((from,to), pairedConnection)
);

1 个答案:

答案 0 :(得分:1)

Cassandra与RDBMS有不同的范例,这在必须进行数据建模的方式中更加明显。您需要记住,首选非正规化,并且您将有重复的数据。

表的定义应基于查询以检索数据,这在问题的定义中有部分说明,例如:

  

找到发送给用户的请求

以表requestsByFrom的初始设计为例,

CREATE TABLE IF NOT EXISTS requests_sent_by_user(
    requester_email TEXT,
    recipient_email TEXT,
    recipient_name TEXT,
    message TEXT,
    created TIMESTAMP
PRIMARY KEY (requester_email, recipient_email)
) WITH default_time_to_live = 864000;

请注意,from是受限制的关键字,可以使用default_time_to_live子句(TTL)的定义来设置expiry信息,该子句将在定义的时间之后删除记录;此值为插入记录后的秒数,示例为10天(864,000秒)。

建议主键为电子邮件地址,但也可以为UUID,不建议使用名称,因为可能有多个人共享同一名称(例如James Smith)或同一人可以拥有姓名的多种书写方式(以下示例Jim SmithJ. Smithj smith可能是指同一个人)。

还添加了名称recipient_name,因为很可能要显示它。应该添加与查询一起显示/使用的任何其他信息。

  

找到收到的用户请求

CREATE TABLE IF NOT EXISTS requests_received_by_user(
    recipient_email TEXT,
    requester_email TEXT,
    requester_name TEXT,
    message TEXT,
    created TIMESTAMP
PRIMARY KEY (recipient_email, requester_email)
) WITH default_time_to_live = 864000;

最好使用batch同时向requests_sent_by_userrequests_received_by_user添加记录,这将确保两个表之间的信息以及TTL(过期)保持一致的数据)将是相同的。

  

存储联系人

该问题中有4个连接表:connectionsactive_connectionsfavourite_connectionspaired_connections,它们之间有什么区别?他们会有不同的规则/用例吗?如果是这种情况,则将它们作为不同的表是有意义的:

CREATE TABLE IF NOT EXISTS connections(
    requester_email TEXT,
    recipient_email TEXT,
    recipient_name TEXT,
    notes TEXT,
    created TIMESTAMP,
    last_update TIMESTAMP,
    is_favourite BOOLEAN,
    is_active BOOLEAN,
    is_paired BOOLEAN,
    PRIMARY KEY (requester_email, recipient_email)
 );

CREATE TABLE IF NOT EXISTS active_connections(
    requester_email TEXT,
    recipient_email TEXT,
    recipient_name TEXT,
    last_update TIMESTAMP,
    PRIMARY KEY (requester_email, recipient_email)
);

CREATE TABLE IF NOT EXISTS favourite_connections(
    requester_email TEXT,
    recipient_email TEXT,
    recipient_name TEXT,
    last_update TIMESTAMP,
    PRIMARY KEY (requester_email, recipient_email)
);

CREATE TABLE IF NOT EXISTS paired_connections(
    requester_email TEXT,
    recipient_email TEXT,
    recipient_name TEXT,
    last_update TIMESTAMP,
    PRIMARY KEY (requester_email, recipient_email)
);

请注意,布尔值标记已删除,其逻辑是如果记录存在于active_connections中,则将假定它是活动连接。

创建新连接时,它可能在不同的表中有多个记录;捆绑所有这些插入或更新,最好使用batch

  

查找给定用户的所有活动联系人

根据建议的表格,如果请求者的电子邮件为test@email.com:

SELECT * FROM active_connections WHERE requester_email = 'test@email.com'
  

将用户更新为收藏夹

将批量更新connections中的记录并将新记录添加到favourite_connections

BEGIN BATCH

UPDATE connections 
SET is_favourite = true, last_update = dateof(now())
WHERE requester_email ='test@email.com' 
  AND recipient_email = 'john.smith@test.com';

INSERT INTO favourite_connections (
    requester_email, recipient_email, recipient_name, last_update
) VALUES (
    'test@email.com', 'john.smith@test.com', 'John Smith', dateof(now())
);
APPLY BATCH;
  

标记连接以进行软删除

可以在禁用所有标志的情况下将连接信息保存在connections中,并将记录从active_connectionsfavourite_connectionspaired_connections

BEGIN BATCH

UPDATE connections 
SET is_active = false, is_favourite = false,
    is_paired = false, last_update = dateof(now())
WHERE requester_email ='test@email.com' 
  AND recipient_email = 'john.smith@test.com';

DELETE FROM active_connections 
WHERE requester_email = 'test@email.com' 
  AND recipient_email = 'john.smith@test.com';

DELETE FROM favourite_connections 
WHERE requester_email = 'test@email.com' 
  AND recipient_email = 'john.smith@test.com';

DELETE FROM paired_connections 
WHERE requester_email = 'test@email.com' 
  AND recipient_email = 'john.smith@test.com';

APPLY BATCH;