我可能不太了解散列/主键在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
是一个数组,列出了对话参与者的userIds。
我需要创建一个服务来查找用户正在参与的所有会话。在MongoDB中(我更熟悉),我会做类似的事情:
Conversation.find({users: {"$in": ['foo']} }).then(....
在DynamoDB中我能做些什么吗?这是一个经常发生的API调用,因此我希望尽可能提高效率。
答案 0 :(得分:2)
这个答案考虑到了对Hunter Frazier的答案的评论,说你不想使用扫描。
使用Query时,需要在操作中指定单个分区键。在您的架构中,这将意味着对userid属性进行分区,该属性是一个集合。 DynamoDB中的分区键必须是顶级标量属性。由于userid不是标量(它是一个集合),因此您不能将此属性用作索引,因此您无法对用户所属的对话执行查询。
如果您需要执行此查询,我建议您重新访问您的架构。具体来说,我建议实施Adjacency list pattern,它适用于包含多对多关系的数据库。
您可以在上面的文章中看到一些关于此答案DynamoDB M-M Adjacency List Design Pattern
的其他说明在您的情况下,您将拥有:
然后,您可以在查询中使用GSI主键来返回用户所属的所有会话。
答案 1 :(得分:1)
我不熟悉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);
});