DynamoDB:查询以查找字符串数组中的项目

时间:2018-05-21 04:07:18

标签: node.js amazon-dynamodb dynogels

我可能不太了解散列/主键在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调用,因此我希望尽可能提高效率。

2 个答案:

答案 0 :(得分:2)

这个答案考虑到了对Hunter Frazier的答案的评论,说你不想使用扫描。

使用Query时,需要在操作中指定单个分区键。在您的架构中,这将意味着对userid属性进行分区,该属性是一个集合。 DynamoDB中的分区键必须是顶级标量属性。由于userid不是标量(它是一个集合),因此您不能将此属性用作索引,因此您无法对用户所属的对话执行查询。

如果您需要执行此查询,我建议您重新访问您的架构。具体来说,我建议实施Adjacency list pattern,它适用于包含多对多关系的数据库。

您可以在上面的文章中看到一些关于此答案DynamoDB M-M Adjacency List Design Pattern

的其他说明

在您的情况下,您将拥有:

  • 主键:ConversationID
  • 排序键:UserID
  • GSI主键:UserID

然后,您可以在查询中使用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);
});