Многие ко многим в Cassandra 3

Как правильно смоделировать отношения «многие ко многим» в Cassandra (используя 3.10 на данный момент)?

Из ответов, которые я смог найти, предлагается денормализация в две таблицы отношений (как здесь, например: Моделирование отношений "многие ко многим" в Cassandra 2 с помощью CQL3). Но есть проблемы с удалением, и эти ответы настолько скудны, что не упоминают никаких подробностей об этом.

Предположим, у нас есть следующие таблицы:

CREATE TABLE foo (
  key UUID PRIMARY KEY,
  content TEXT
)
CREATE TABLE bar (
  key UUID PRIMARY KEY,
  content TEXT
)
CREATE TABLE foo_bar (
  foo UUID,
  bar UUID,
  PRIMARY KEY (foo, bar)
)
CREATE TABLE bar_foo (
  bar UUID,
  foo UUID,
  PRIMARY KEY (bar, foo)
)

Кажется, это предлагаемый ответ. Однако что происходит, когда мы пытаемся удалить запись bar? Обновить таблицу bar_foo очень просто:

DELETE FROM bar_foo WHERE bar = <bar_key>

Однако попытка обновить таблицу foo_bar не удалась:

DELETE FROM foo_bar WHERE bar = <bar_key>

со следующей ошибкой:

InvalidRequest: Error from server: code=2200 [Invalid query] message="Some partition key parts are missing: foo"

Это связано с тем, что первичным ключом для таблицы foo_bar является (foo, bar), и мы указываем только вторую часть первичного ключа в предложении WHERE инструкции DELETE. Cassandra, видимо, требует префикс первичного ключа, а bar без foo префиксом не является.

Теперь изменение первичного ключа на (bar, foo) не поможет. В конце концов, что бы вы сделали, если бы запись foo была удалена? И, в любом случае, вся цель таблицы foo_bar состоит в том, чтобы иметь возможность найти все записи bar, соответствующие данной записи foo, а оператор SELECT также требует префикса первичного ключа в Предложение WHERE (которое по необходимости должно быть foo).

Невозможно выполнить SELECT, а затем DELETE, поскольку SELECT по bar не будет работать, поскольку он не является префиксом первичного ключа.

Итак, что делать с отношениями «многие ко многим», когда на картинке есть удаления? Возможно ли это сделать должным образом?


person silverberry    schedule 14.06.2017    source источник
comment
вы можете создать материализованное представление, и кассандра позаботится об этом... для сценария вида bar_foo и foo_bar   -  person undefined_variable    schedule 14.06.2017
comment
О, у Cassandra 3 есть материализованные виды. Хорошо! Спасибо.   -  person silverberry    schedule 14.06.2017


Ответы (1)


Используйте наборы. https://docs.datastax.com/en/cql/3.3/cql/cql_using/useSet.html

CREATE TABLE foo (
  key UUID PRIMARY KEY,
  content TEXT
)
CREATE TABLE bar (
  key UUID PRIMARY KEY,
  content TEXT
)
CREATE TABLE foo_jn_bar (
  foo UUID PRIMARY KEY,
  bar set<UUID>
)
CREATE TABLE bar_jn_jn (
  bar UUID PRIMARY KEY,
  foo set<UUID>
)

Если вы будете следовать реляционной привычке, у вас будет огромное дублирование данных на диске.

person Sergey Nagaytsev    schedule 21.11.2017