Модель данных приложения внутренней сети с Cassandra - PullRequest
0 голосов
/ 03 июля 2019

Я работаю над созданием приложения, которое позволит пользователям отправлять запросы на соединение друг с другом, видеть их отправленные или полученные запросы, делать заметки во время их взаимодействия для последующего использования, если они подключены, и удалять пользователей из их списков контактов.

В СУБД схема будет выглядеть следующим образом:

таблица Пользователь со столбцом

  • uid (уникальная строка для каждого пользователя)

таблица Запрос со столбцами:

  • от - идентификатор пользователя

  • до - идентификатор пользователя Первичный ключ (от, до)

  • создано - отметка времени

  • сообщение - строка

  • expiry - отметка времени

таблица Соединение со столбцами:

  • от - идентификатор пользователя

  • до - идентификатор пользователя

Первичный ключ (от, до)

  • примечания - строка

  • создано - отметка времени

  • изменено - отметка времени

  • isFavourite - это избранное пользователя, значение 0 или 1

  • isActive - мягкое удаление, значение 0 или 1

  • pairedConnection - показывает, была ли деактивирована связь между и из (пользователь удалил пользователя из своего списка контактов), значение 0 или 1

Запросы, на которые я рассчитываюнеобходимо:

  • найти отправленные запросы для пользователя

  • найти полученные запросы для пользователя

  • найти все активные контакты данного пользователя

  • найти все избранное пользователя

  • найти всех удаленных пользователейпредоставленные пользователем из их списков

  • обновлять заметки, сделанные пользователем при встрече с другим пользователем, с которым он связан

  • обновить пользователя как избранного

  • пометить соединение для мягкого удаления

Я пытаюсь смоделировать это в Кассандре, ноЯ не понимаю, какие клавиши выбрать для максимальной эффективности.

Пока у меня есть следующие идеи, и я хотел бы получить отзывы от более опытных пользователей 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 Ответ

1 голос
/ 03 июля 2019

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 является ограниченным ключевым словом, информация expiry может быть установлена ​​с определением предложения default_time_to_live (TTL), которое удалит запись после определенного времени; это значение равно количеству секунд после вставки записи, например, 10 дней (864 000 секунд).

Предполагается, что первичным ключом является адрес электронной почты, но это также может быть UUID, имя не рекомендуется, так как может быть несколько человек с одинаковым именем (например, James Smith), или один и тот же человек может иметь несколько способов. написать имя (по примеру Jim Smith, J. Smith и j 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;

Рекомендуется добавлять записи в requests_sent_by_user и requests_received_by_user одновременно, используя партию , что обеспечит согласованность информации между обеими таблицами, а также TTL (истечение срока действия данные) будут одинаковыми.

хранение контактов

В вопросе есть 4 таблицы соединений: connections, active_connections, favourite_connections, paired_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, предполагается, что это активное соединение.

Когда создается новое соединение, оно может иметь несколько записей в разных таблицах; для объединения всех этих вставок или обновлений предпочтительно использовать пакет

найти все активные контакты данного пользователя

На основании предложенных таблиц, если адрес электронной почты запрашивающей стороны - 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_connections, favourite_connections и paired_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;
...