#amazon-web-services #aws-lambda #nosql #amazon-dynamodb #dynamodb-queries
#amazon-веб-сервисы #aws-lambda #nosql #amazon-dynamodb #dynamodb-запросы
Вопрос:
У меня есть таблица DynamoDB с пользователями и друзьями.Схема выглядит как удар. Здесь пользователь 1 (том) и пользователь 2 (Роб) являются друзьями.
-------- --------- ----------
| PK | SK | UserName |
-------- --------- ----------
| USER#1 | USER#1 | tom |
| USER#2 | USER#2 | bob |
| USER#3 | USER#3 | rob |
| FRD#1 | USER#2 | |
| FRD#2 | USER#1 | |
-------- --------- ----------
- Возможно ли получить имена друзей пользователя 1 (tom) в одном запросе?
- Если нет, то какой эффективный способ запроса.
Любая помощь была бы очень признательна.
Что я делаю в настоящее время, так это:
Шаг 1. Найдите всех друзей пользователя 1.
let frdParams = {
TableName : "TABLE_NAME",
IndexName: "SK-PK-index",
KeyConditionExpression: "SK = :userId AND begins_with(PK, :friend)",
ExpressionAttributeValues: {
":userId": {S: userId},
":friend": {S: "FRIEND#"}
}
};
const frdRes = await ddb.query(frdParams).promise();
Шаг 2: как только я получу всех пользователей, запустите больше запросов в цикле.
for (const record of frdRes.Items) {
let recordX = aws.DynamoDB.Converter.unmarshall(record);
let friendId = itemX.PK.replace("FRD", "USER")
let userParams = {
TableName : "TABLE_NAME",
KeyConditionExpression: "PK = :userId AND SK = :userId",
ExpressionAttributeValues: {
":userId": {S: friendId}
}
};
const userRes = await ddb.query(userParams).promise();
}
Комментарии:
1. Невозможно получить друзей тома за один запрос. «Секретный соус» заключается не в умном запросе, а в том, как вы структурируете свои данные. Являетесь ли вы супругом этой модели данных или у вас есть возможность изменить ее для поддержки этого шаблона доступа?
2. Привет @SethGeoghegan — а, понятно. Нет, я недавно начал учиться, поэтому готов к изменениям.
3. это хорошее чтение для составления схем с одной таблицей: trek10.com/blog/dynamodb-single-table-relational-modeling
Ответ №1:
Моделирование данных в DynamoDB требует иного мышления, чем при работе с базами данных SQL. Чтобы получить максимальную отдачу от DynamoDB, необходимо учитывать шаблоны доступа к приложениям и хранить данные таким образом, чтобы они поддерживали эти варианты использования.
Похоже, что ваш шаблон доступа — «поиск друзей по идентификатору пользователя». Существует много способов реализовать этот шаблон доступа, но я дам вам несколько идей о том, как этого можно достичь.
Идея 1. денормализовать ваши данные
Вы можете создать list
атрибут и сохранить список друзей каждого пользователя. Это сделало бы поиск друзей пользователем очень простым!
Как и в случае с любым шаблоном доступа, этот подход имеет ограничения. Максимальный размер атрибутов DynamoDB составляет 400 КБ, поэтому вы будете ограничены списком друзей такого размера. Кроме того, вы не сможете выполнять запросы на основе значений этого атрибута, поэтому он не будет поддерживать дополнительные шаблоны доступа. Но это очень просто!
Идея 2. Создайте коллекцию элементов, сохраняя друзей в USER#<id>
разделе.
Это типичный шаблон для представления отношений «один ко многим» в DynamoDB. Допустим, вы определяете дружеские отношения с помощью PK of USER#<user_id>
и SK of FRIEND#<friend_id>
. Ваша таблица будет выглядеть следующим образом:
Вы можете получить друзей данного пользователя, выполнив поиск по ключу раздела пользователи для сортировки ключей этого begins_with
ДРУГА.
Это всего лишь две идеи, и есть много других (и, вероятно, лучших) способов моделирования дружеских отношений в DynamoDB. В приведенных мною примерах отношение один ко многим (у одного пользователя много друзей). Более вероятно, что у вас будет отношение «многие ко многим» к модели, что может быть сложно в DynamoDB (и совсем другая тема!)
Если «многие ко многим» звучит так, как у вас есть, в AWS есть статья, описывающая моделирование отношений «многие ко многим«, которая может оказаться хорошей отправной точкой.
Комментарии:
1. Как вы сказали, первая идея имеет ограничение в 400 КБ, вторая идея такая же, как у меня? нет?
2. В вашем примере показано, что объект friends смоделирован как отдельный элемент от объекта user. Это означает, что вам нужно будет выполнить больше, чем один запрос, чтобы получить друзей пользователя. В моем решении друзья пользователей моделируются в разделе пользователя, что позволяет получать всех друзей данного пользователя в одном запросе. Аналогично вашему решению, но не требует многократного обращения к базе данных.
3. Я только что понял, что ваш первый запрос для друзей использует индекс. В этом случае ваше решение похоже на мою идею 2, но я не использую индекс. Отличный пример того, как существует несколько способов реализации заданного шаблона доступа в DDB!