Дизайн одной таблицы приложения для чата на DynamoDB, проверка того, в правильном ли направлении

#amazon-web-services #amazon-dynamodb #amazon-dynamodb-data-modeling

Вопрос:

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

Шаблоны доступа, о которых я до сих пор думал, таковы —

  1. Получите сведения о пользователе по идентификатору пользователя.
  2. Получите список разговоров, в которых участвует пользователь.
  3. Получить список сообщений, созданных пользователем
  4. Соберите всех участников беседы
  5. Получать все сообщения о разговоре

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

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

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

Дизайн одного стола - Компоновка стола

Ответ №1:

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

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

Я бы предложил другую модель — она состоит из таблицы с Глобальным вторичным индексом (GSI1). Планировка выглядит так:

Базовый Стол:

  • Ключ раздела: PK
  • Ключ сортировки: SK

Глобальный вторичный индекс GSI1:

  • Ключ раздела: GSI1PK
  • Ключ сортировки: GSI1SK

Базовый Стол

Базовый Стол

GSI 1

GSI1

Шаблоны доступа

1.) Получить сведения о пользователе по идентификатору пользователя.

GetItem в базовой таблице с ключом раздела = PK = U#<id> и ключом сортировки SK = USER

2.) Получите список разговоров, в которых участвует пользователь.

Запрос к базовой таблице с ключом раздела = PK = U#<id> и Ключом сортировки SK = starts_with(CONV#)

3.) Получить список сообщений, созданных пользователем

Запрос на GSI1 с ключом раздела GSI1PK = U#<id>

4.) Соберите всех участников беседы

Запрос к базовой таблице с ключом раздела = PK = CONV#<id> и Ключом сортировки SK starts_with(U#)

5.) Получайте все сообщения из разговора

Запрос к базовой таблице с ключом раздела PK = CONV#<id> и ключом сортировки SK starts_with(MSG#)

6.) Также хочу получить доступ к сообщениям разговора по диапазону дат, до сих пор я этого не понял.

DynamoDB выполняет сортировку по порядку байтов в разделе — если вы отформатируете все даты в соответствии с ISO 8601 в часовом поясе UTC, вы можете выполнить запрос диапазона, например:

Запрос к базовой таблице с ключом раздела PK = CONV#<id> и ключом сортировки SK between(MSG#2021-09-20, MSG#2021-09-30)

Комментарии:

1. Спасибо Морису за подробное объяснение. Просто хочу знать, что было бы более эффективным и экономичным. Что делать, если при создании сообщения оно записывается как в раздел пользователя, так и в раздел беседы? Таким образом, также работает шаблон 3-го доступа.

2. Каков ваш вариант использования этого шаблона доступа? Это то, что я понял меньше всего. С экономической точки зрения это не должно иметь большого значения — в обоих случаях вы дублируете затраты на хранение и доступ для чтения/записи. Вот почему я бы выбрал решение с меньшими накладными расходами, то есть GSI.

3. У меня запланирована функция для отображения статистики, например, количества сообщений, отправленных пользователем по неделям, месяцам и т. Д., Если пользователь является участником группового чата. Это был бы основной случай использования.

4. В этом случае, вероятно, лучше сохранить элемент с совокупной статистикой, подключить Лямбду к потоку DynamoDB и заставить эту Лямбду обновлять статистику при создании/удалении новых сообщений. Это дешевле.

5. Ладно, звучит неплохо. Спасибо, Морис.