DynamoDB: запрос для поиска элемента в массиве строк
Возможно, я не совсем понимаю, как хэш / первичные ключи работают в DynamoDB, но я пытаюсь создать модель (используя Serverless + Dynogels/NodeJS) для службы сообщений.
Модель выглядит так:
const ConversationORM = dynogels.define('Conversation', {
hashKey: 'id',
timestamps: true,
tableName: config.CONVERSATION_TABLE,
schema: {
id: Joi.string(),
users: Joi.array(), // e.g. ['foo', 'bar', 'moo']
messages: Joi.array()
}
})
Как вы видете, users
массив, в котором перечислены идентификаторы участников беседы
Мне нужно создать сервис, который находит все разговоры, в которых участвует пользователь. В MongoDB (с которой я гораздо лучше знаком) я бы сделал что-то вроде:
Conversation.find({users: {"$in": ['foo']} }).then(....
Есть ли что-то эквивалентное, что я могу сделать в DynamoDB? Это вызов API, который будет происходить довольно часто, поэтому я надеюсь сделать его максимально эффективным.
2 ответа
Этот ответ принимает во внимание комментарий к ответу Хантера Фрейзера о том, что вы не хотите использовать сканирование.
При использовании запроса необходимо указать один ключ раздела в операции. В вашей схеме это будет означать разбиение по атрибуту userid, который является набором. Ключи разделов в DynamoDB должны быть скалярным атрибутом верхнего уровня. Поскольку идентификатор пользователя не является скалярным (это набор), вы не можете использовать этот атрибут в качестве индекса, и, следовательно, вы не можете сделать запрос для разговоров, частью которых является пользователь.
Если вам нужно сделать этот запрос, я бы предложил пересмотреть вашу схему. В частности, я бы предложил реализовать шаблон списка Смежности, который хорошо работает в базах данных, содержащих отношения "многие ко многим".
Вы можете видеть некоторые дополнительные примечания к статье выше, которую я написал для этого ответа. Шаблон проектирования списка смежности MM DynamoDB
В вашем случае вы бы имели:
- Первичный ключ: ConversationID
- Ключ сортировки: идентификатор пользователя
- Первичный ключ GSI: идентификатор пользователя
Затем вы можете использовать первичный ключ GSI в запросе, чтобы вернуть все разговоры, частью которых является пользователь.
Я не знаком с Dynogels или Serverless, но если он использует обычный API, это может сработать:
var params = {
ExpressionAttributeNames: {
"U": "users"
},
ExpressionAttributeValues: {
":a": {
S: "John Doe"
}
},
FilterExpression: "Author = :a",
ProjectionExpression: "#U",
TableName: "Conversations"
};
dynamodb.scan(params, function (err, data) {
if (err) console.log(err, err.stack);
else console.log(data);
});