Примеры для DynamicDB Materialized Graph Pattern

Я начал изучать DynamoDB, но застрял, читая эту часть о материализованном графовом шаблоне: лучшие практики для управления отношениями "многие ко многим".

Я предполагаю, что у меня есть некоторые идеи, но пока не понимаю всего этого. Насколько я понимаю шаблон, основная таблица хранит ребра, и у каждого ребра могут быть свойства (атрибут data).

Например (взято из показанных таблиц): Узел 1 (PK 1) имеет ребро для Узла 2 типа DATE, а ребро имеет тип BIRTH (SK DATE | 2 | BIRTH).

Я полагаю, что это будет примерно так же, как() - [: BIRTH] → (: DATE {id: 2}) в Cipher, верно?

Но после этого становится неясно, как все сходится. Например:

  1. Может ли атрибут данных быть картой?
  2. Должен ли атрибут данных записываться в два места при записи? Например, под (1, ДАТА | 2 | РОЖДЕНИЕ) и (2, ДАТА | 2)?
  3. Если я хочу добавить нового человека, родившегося 1980-12-19, должен ли я сначала искать соответствующий узел?
  4. Как я могу получить все свойства, связанные с узлом? Как получить все свойства, связанные с ребром?
  5. Как я могу запросить соседние узлы?
  6. ...

Может кто-нибудь объяснить мне, как все сходится, пройдя через несколько вариантов использования?

Заранее спасибо.

Ответ 1

Надеюсь, это ответит на все ваши вопросы. Здесь пара вводных вещей. Я буду использовать общую таблицу для всех моих примеров. Ключ хеша - это node_a а ключ сортировки - это node_b. Существует GSI обратного просмотра, где node_b - это ключ хеша, а node_a - ключ сортировки.

1. Может ли атрибут данных быть картой?

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

2. Должен ли атрибут данных записываться в два места при записи?

Атрибут данных должен быть записан только в одном месте. В качестве примера даты рождения вы можете сделать одну из следующих записей DynamoDB:

node_a    | node_b    | data
----------|-----------|---------------
user-1    | user-1    | {"birthdate":"2000-01-01", "firstname": "Bob", ...}
user-1    | birthdate | 2000-01-01

В первой строке мы создали ребро из узла user-1 которое возвращается на себя. Во втором ряду мы создали грань от user-1 до birthdate. В любом случае это хорошо, и лучший выбор зависит от того, как вы будете получать доступ к вашим данным. Если вам нужно найти пользователей с датой рождения в заданном диапазоне, вам следует создать узел с birthdate. Если вам просто нужно найти информацию о пользователях по их идентификатору, вы можете использовать любую стратегию, но первая строка обычно будет более эффективно использовать пропускную способность вашей таблицы.

3. Если я хочу добавить нового человека, родившегося 1980-12-19, должен ли я сначала искать соответствующий узел?

Нет. Просто вставьте одну из строк из примера выше.

Вам нужно искать узел только в том случае, если существует более сложный шаблон доступа, например, "обновить имя человека, родившегося в 1980-12-19". В этом случае вам потребуется поискать по дате рождения, чтобы получить узел человека, а затем изменить что-то, связанное с узлом человека. Однако этот вариант использования на самом деле является двумя разными операциями. Вы можете перефразировать это предложение как "Найти человека, который родился в 1980-12-19, и обновить имя", что делает эти две операции более очевидными.

4. (а) Как я могу получить все свойства, связанные с узлом?

Предположим, вы хотите найти все ребра для "myNode". Вы запросите основную таблицу с помощью ключевого выражения условия node_a="myNode" и запросите GSI обратного просмотра с ключевым условием выражения node_b="myNode". Это эквивалент SELECT * FROM my_table WHERE node_a="myNode" OR node_b="myNode".

4. (б) Как получить все свойства, связанные с ребром?

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

node_a    | node_b    | data
----------|-----------|---------------
thing-1   | thing-2   | Is the data here?
thing-2   | thing-1   | Or here?

Если вы знаете порядок краевых узлов (т. node_a node_b узел является node_a и node_b), то вам потребуется только одна операция GetItem для извлечения данных. Если вы не знаете, в каком порядке расположены узлы, то вы можете использовать BatchGetItems для поиска обеих строк в таблице (должна существовать только одна из строк, если вы не делаете что-то особенно сложное с участием ориентированного графа).

5. Как я могу запросить соседние узлы?

Смежные узлы - это просто два узла, которые имеют ребро, соединяющее их. Вы бы использовали тот же запрос, что и 4a, за исключением того, что вместо интереса к атрибуту data вас интересуют идентификаторы других узлов.

Еще несколько примеров