Соотношение "многие ко многим": глобальный вторичный индекс против списка смежности

Для представления отношения "многие ко многим" в DB "Динамо" я обычно видел два подхода: глобальный вторичный индекс (GSI) и список смежности. Теперь мой вопрос, когда использовать какой?

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

Players table
--------------
Partition | Sort
-----------------
Player 1  | Game 1
Player 1  | Game 2
Player 2  | Game 1
Player 3  | Game 2

Games GSI
-----------
Partition | Sort
-----------------
Game 1    | Player 2
Game 1    | Player 2
Game 2    | Player 1
Game 2    | Player 3 

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

Все это кажется простым и логичным для реализации... Пока данные не станут немного сложнее. Что если и у Игроков, и у Игр свой набор атрибутов? Скажем, у игры есть атрибут, когда она была запущена, а у игрока есть такие атрибуты, как имя пользователя и личный счет игры. Как они проецируются на каждую таблицу и GSI?

Например, требуемые прогнозы будут примерно такими

Получить игроков, участвующих в игре

// query made with game id
{
  start_date: '2018-11-04T13:00Z',
  status: 'IN_PROGRESS',
  players: [
    {
      username: 'starkshark',
      points: 200
    },
    {
      username: 'coldshot',
      points 300
    }
  ]
}

Получить игры, в которых участвовал игрок

// query made with player id
{
  username: 'starkshark',
  games: [
    {
      status: 'IN_PROGRESS',
      start_date: '....'
    },
    {
      status: 'ENDED',
      start_date: '...',
      end_date: '...'
    }
  ]
}

Или это пограничный случай, когда нужно использовать шаблон списка смежности? Из того, что я прочитал в целом о списках смежности, довольно сложно реализовать простое отношение "многие ко многим", как в приведенном выше примере с онлайн-играми. Что я понял, это предназначено для моделирования графиков с несколькими узлами, связанными друг с другом. Конечно, в этом случае узлами будут Игры и Игроки (и, возможно, любая другая сущность, необходимая в модели).

TLDR: Таким образом, все сводится к последним вопросам, когда существует возможность выбора списка смежности, когда существует отношение "многие ко многим" между сущностями, имеющими свой собственный набор атрибутов, или существует менее сложная структура данных для модели?

1 ответ

Решение

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

Id1       | Id2     | Data
- - - - - - - - - - - - - - - - - - - 
User1     | User1   | {email=...}

Кроме того, вы можете смоделировать атрибут как ребро от объекта к типу атрибута.

Id1       | Id2     | Data
- - - - - - - - - - - - - - - - - - - 
User1     | Email   | bob@...

Все зависит от того, как вы хотите иметь возможность запрашивать ваши данные. Преимущество второго подхода состоит в том, что у вас может быть GSI, где Id2 является ключом раздела, и Data это ключ диапазона, который позволит вам эффективно найти всех пользователей, которые соответствуют определенному значению атрибута.

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

Другие вопросы по тегам