Должны ли списки смежности DynamoDB использовать отдельные ключи разделов для моделирования каждого типа отношений? - PullRequest
0 голосов
/ 18 ноября 2018

Контекст

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

Требования

Например, допустим, мы хотим сделать следующее:

  • Пользователям могут понравиться комментарии
  • Пользователи могут следить за комментариями
  • Комментарии могут отображать пользователей, которым это нравится
  • Комментарии могут отображать пользователи, которые следуют за ним
  • Профили пользователей могут показывать комментарии, которые им нравятся
  • Профили пользователей могут отображать комментарии, за которыми они следят

Итак, по сути, у нас есть многие ко многим (пользовательские комментарии <=>) ко многим (например, или подписчикам).

Примечание: этот пример намеренно сокращен, и на практике будет гораздо больше связей с моделью, поэтому я пытаюсь придумать что-то расширяемое здесь.

Базовый

Следующие данные верхнего уровня, вероятно, будут общими в любом представлении списка смежности:

First_id(Partition key)         Second_id(Sort Key)         Data
-------------                   ----------                  ------
User-Harry                      User-Harry                  User data
User-Ron                        User-Ron                    User data
User-Hermione                   User-Hermione               User data
Comment-A                       Comment-A                   Comment data
Comment-B                       Comment-B                   Comment data
Comment-C                       Comment-C                   Comment data

Кроме того, для каждой таблицы ниже будет эквивалентный глобальный вторичный индекс с заменой ключей раздела и сортировки.

Пример данных

Это то, что я хотел бы смоделировать в DynamoDB:

  1. Гарри нравится комментарий A
  2. Гарри нравится комментарий B
  3. Гарри следует за комментарием A
  4. Рону нравится комментарий B
  5. Гермионе нравится комментарий C

Вариант 1

Используйте третий атрибут для определения типа отношения:

First_id(Partition key)         Second_id(Sort Key)         Data
-------------                   ----------                  ------
Comment-A                       User-Harry                  "LIKES"
Comment-B                       User-Harry                  "LIKES"
Comment-A                       User-Harry                  "FOLLOWS"
Comment-B                       User-Ron                    "LIKES"
Comment-C                       User-Hermione               "FOLLOWS"

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

Вариант 2

Измените ключи для представления отношения:

First_id(Partition key)         Second_id(Sort Key)
-------------                   ----------
LikeComment-A                   LikeUser-Harry
LikeComment-B                   LikeUser-Harry
FollowComment-A                 FollowUser-Harry
LikeComment-B                   LikeUser-Ron
FollowComment-C                 FollowUser-Hermione

Это позволяет эффективно запрашивать независимо:

  1. Комментирует лайки
  2. Комментарий следует
  3. Мне нравится
  4. Пользователь следует

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

Вариант 3

Пропустить списки смежности в целом и использовать отдельные таблицы, возможно, одну для Users, одну для Likes и одну для Follows.

Вариант 4

Традиционная реляционная база данных. Хотя я не планирую идти по этому пути, потому что это личный проект, и я хочу изучить DynamoDB, если этот является правильным способом думать о вещах, мне бы хотелось услышать почему.

Заключение

Спасибо, что прочитали это далеко! Если я могу что-то сделать, чтобы упростить вопрос или что-то прояснить, пожалуйста, дайте мне знать:)

Я ознакомился с рекомендациями AWS и с этой публикацией SO-многие-ко-многим , и ни один из них, по-видимому, не касается отношения «многие-ко-многим (со многими)», поэтому любые ресурсы или рекомендации с благодарностью.

1 Ответ

0 голосов
/ 18 ноября 2018

Ваш вариант 1 невозможен, поскольку он не имеет уникальных первичных ключей. В ваших примерах данных вы можете видеть, что у вас есть две записи для (Comment-A, User-Harry).

Раствор 1

Способ реализовать то, что вы ищете, это использовать немного разные атрибуты для вашей таблицы и GSI. Если Гарри нравится Комментарий А, тогда ваши атрибуты должны быть:

hash_key: User-Harry
gsi_hash_key: Comment-A
sort_key_for_both: Likes-User-Harry-Comment-A

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

Решение 2

Вы могли бы сделать отношения объектом высшего уровня. Например, Likes-User-Harry-Comment-A будет иметь две записи в базе данных, потому что она «смежна» с User-Harry и Comment A.

Это дает вам гибкость, если вы хотите смоделировать более сложную информацию об отношениях в будущем (включая возможность описать отношения между отношениями, такие как Likes-User-Ron-User-Harry Causes Follows-User-Ron-User-Harry).

Однако эта стратегия требует хранения большего количества элементов в базе данных, и это означает, что сохранение «подобно» (чтобы его можно было запрашивать) не является атомарной операцией. (Но вы можете обойти это, только написав сущность отношения, а затем используйте DynamoDBStreams + Lambda для записи записей для двух записей, которые я упомянул в начале этого решения.)

Обновление: используя транзакции DynamoDB, сохранение «как» таким образом может фактически быть полностью КИСЛОТОЙ операцией.

...