聊天应用程序的Cassandra模式

问题描述 投票:10回答:2

我已经通过了article,这是我从中得到的架构。这对于我的用于维护用户状态的应用程序很有帮助,但是如何扩展它以维护一对一的聊天档案和用户之间的关系,关系意味着人们对我来说属于特定的组。我对此并不陌生,需要一种解决方法。

需求:

  • 我想在表中的用户-用户之间存储消息。
  • [每当用户希望由用户加载消息时。我想找回它们并将其发送给用户。
  • 我想在用户请求后从其他用户检索所有消息。
  • 并且还想存储用户类别。我的意思是,例如,user1和user2属于“家庭”,user3,user4,user1属于朋友等。此组可以是用户指定的自定义名称。

这是我到目前为止尝试过的:

CREATE TABLE chatarchive (
   chat_id uuid PRIMARY KEY,
   username text,
   body text
)

CREATE TABLE chatseries (
username text,
    time timeuuid,
    chat_id uuid,
    PRIMARY KEY (username, time)
) WITH CLUSTERING ORDER BY (time ASC)

CREATE TABLE chattimeline (
    to text,
username text,
    time timeuuid,
    chat_id uuid,
    PRIMARY KEY (username, time)
) WITH CLUSTERING ORDER BY (time ASC)

下面是我目前拥有的架构:

CREATE TABLE users (
   username text PRIMARY KEY,
   password text
)    

CREATE TABLE friends (
    username text,
    friend text,
    since timestamp,
    PRIMARY KEY (username, friend)
)

CREATE TABLE followers (
    username text,
    follower text,
    since timestamp,
    PRIMARY KEY (username, follower)
)

CREATE TABLE tweets (
    tweet_id uuid PRIMARY KEY,
    username text,
    body text
)
CREATE TABLE userline (
    username text,
    time timeuuid,
    tweet_id uuid,
    PRIMARY KEY (username, time)
) WITH CLUSTERING ORDER BY (time DESC)

CREATE TABLE timeline (
    username text,
    time timeuuid,
    tweet_id uuid,
    PRIMARY KEY (username, time)
) WITH CLUSTERING ORDER BY (time DESC)
cassandra cql
2个回答
12
投票

使用C *,您需要以使用方式存储数据。因此,让我们看一下这种情况:

  • 我想在表中的用户-用户之间存储消息。
  • 每当用户希望由用户加载消息时。我想找回它们并将其发送给用户。

    CREATE TABLE chat_messages (
        message_id uuid,
        from_user text,
        to_user text,
        body text,
        class text,
        time timeuuid,
        PRIMARY KEY ((from_user, to_user), time)
    ) WITH CLUSTERING ORDER BY (time ASC);
    

这将允许您检索两个用户之间的消息时间轴。请注意,使用了复合主键,以便为每对用户创建宽行。

SELECT * FROM chat_messages WHERE from_user = 'mike' AND to_user = 'john' ORDER BY time DESC ;

  • 我想在用户请求时从其他用户检索所有消息给用户。

CREATE INDEX chat_messages_to_user ON chat_messages (to_user);

这可以让您做:

SELECT * FROM chat_messages WHERE to_user = 'john';
  • 并且还想存储用户类别。我的意思是,例如,user1和user2属于“家庭”,user3,user4,user1属于朋友等。此组可以是用户指定的自定义名称。

CREATE INDEX chat_messages_class ON chat_messages (class);

这将允许您执行以下操作:

SELECT * FROM chat_messages WHERE class = 'family';

请注意,在这种数据库中,对数据进行标准化处理是一种很好的做法。这意味着一次又一次使用类的名称并不是一个坏习惯。

还要注意,我没有使用'chat_id'或'chats'表。我们可以轻松地添加它,但是我觉得您的用例并不需要它,因为它已经被提出。通常,您不能在C *中进行联接。因此,使用聊天ID意味着两个查询。

编辑:次要索引效率低下。使用C * 3.0,物化视图将是更好的实现]


7
投票

[有一个由Alan Chandler在github上创建的聊天应用程序,它具有您请求的功能:

它使用两阶段认证。首先,在论坛中对用户进行验证,然后在聊天数据库中对用户进行验证。

这是架构的第一个validation部分(模式位于inc/user.sql中:]

inc/user.sql

这是架构的第二个validation部分(模式位于BEGIN; CREATE TABLE users ( uid integer primary key autoincrement NOT NULL, time bigint DEFAULT (strftime('%s','now')) NOT NULL, name character varying NOT NULL, role text NOT NULL DEFAULT 'R', -- A (CEO), L (DIRECTOR), G (DEPT HEAD), H (SPONSOR) R(REGULAR) cap integer DEFAULT 0 NOT NULL, -- 1 = blind, 2 = committee secretary, 4 = admin, 8 = mod, 16 = speaker 32 = can't whisper( OR of capabilities). password character varying NOT NULL, -- raw password rooms character varying, -- a ":" separated list of rooms nos which define which rooms the user can go in isguest boolean DEFAULT 0 NOT NULL ); CREATE INDEX userindex ON users(name); -- Below here you can add the specific users for your set up in the form of INSERT Statements -- This list is test users to cover the complete range of functions. Note names are converted to lowercase, so only put lowercase names in here INSERT INTO users(uid,name,role,cap,password,rooms,isguest) VALUES (1,'alice','A',4,'password','7',0), -- CEO class user alice (2,'bob','L',3,'password','8',0), -- DIRECTOR class user bob (3,'carol','G',2,'password','7:8:9',0), -- DEPT HEAD class user carol 中):

data/chat.sql

以下是聊天室[[rooms的架构,您可以看到用户classes及其示例:

data/chat.sql
用户还有另一个表来指示对话的

参与

CREATE TABLE users ( uid integer primary key NOT NULL, time bigint DEFAULT (strftime('%s','now')) NOT NULL, name character varying NOT NULL, role char(1) NOT NULL default 'R', rid integer NOT NULL default 0, mod char(1) NOT NULL default 'N', question character varying, private integer NOT NULL default 0, cap integer NOT NULL default 0, rooms character_varying );

archives

记录如下:CREATE TABLE rooms ( rid integer primary key NOT NULL, name varchar(30) NOT NULL, type integer NOT NULL -- 0 = Open, 1 = meeting, 2 = guests can't speak, 3 moderated, 4 members(adult) only, 5 guests(child) only, 6 creaky door ) ; INSERT INTO rooms (rid, name, type) VALUES (1, 'The Forum', 0), (2, 'Operations Gallery', 2), -- Guests Can't Speak (3, 'Dungeon Club', 6), -- creaky door (4, 'Auditorium', 3), -- Moderated Room (5, 'Blue Room', 4), -- Members Only (in Melinda's Backups this is Adults) (6, 'Green Room', 5), -- Guest Only (in Melinda's Backups this is Juveniles AKA Baby Backups) (7, 'The Board Room', 1), -- Various meeting rooms - need to be on users room list

Edit:

但是,这种类型的数据建模不适用于CREATE table wid_sequence ( value integer); INSERT INTO wid_sequence (value) VALUES (1); CREATE TABLE participant ( uid integer NOT NULL REFERENCES users (uid) ON DELETE CASCADE ON UPDATE CASCADE, wid integer NOT NULL, primary key (uid,wid) ); 。因为,在CREATE TABLE chat_log ( lid integer primary key, time bigint DEFAULT (strftime('%s','now')) NOT NULL, uid integer NOT NULL REFERENCES user (uid) ON DELETE CASCADE ON UPDATE CASCADE, name character varying NOT NULL, role char(1) NOT NULL, rid integer NOT NULL, type char(2) NOT NULL, text character varying ); 中,您的数据不适合在一台计算机上,因此联接不可用。因此,在Cassandra Cassandra中数据是实际的选择。检查下面的Cassandra表的非规范化版本:denormalizing
现在为了检索数据,您将使用以下查询:

每当用户要加载

用户的消息]时>。我想找回它们并将其发送给用户。

chat_log
我想

在用户请求时检索来自不同用户的所有消息

]CREATE TABLE chat_log ( lid uuid, time timestamp, sender text NOT NULL, receiver text NOT NULL, room text NOT NULL, sender_role varchar NOT NULL, receiver_role varchar NOT NULL, rid decimal NOT NULL, status varchar NOT NULL, message text, PRIMARY KEY (sender, receiver, room) -- PRIMARY KEY (sender, receiver) if you don't want the messages to be separated by the rooms ) WITH CLUSTERING ORDER BY (time ASC);
我要

存储和检索用户类别

SELECT * FROM chat_log WHERE sender = 'bob' ORDER BY time ASC
对数据建模之后。您需要创建索引以快速高效地进行查询,如下所示:

    用于有效地检索来自不同用户的所有消息
  • 给用户
创建索引chat_log_uid开启chat_log(发送方);CREATE INDEX chat_log_uid打开chat_log(接收方);

    用于有效地从用户
  • classes检索所有消息
创建索引chat_log_class打开chat_log(sender_role);创建索引chat_log_class打开chat_log(receiver_role);

我相信这些示例将为您提供所需的

方法

如果您想了解有关Cassandra数据建模的更多信息,可以在下面查看:

© www.soinside.com 2019 - 2024. All rights reserved.