1

我可能不太了解哈希/主键在 DynamoDB 中的工作原理,但我正在尝试为消息传递服务创建一个模型(使用无服务器 + 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是一个数组,其中列出了对话参与者的用户 ID。

我需要创建一个服务来查找用户参与的所有对话。在 MongoDB(我更熟悉)中,我会做类似的事情:

Conversation.find({users: {"$in": ['foo']} }).then(.... 

我可以在 DynamoDB 中做一些等效的事情吗?这是一个经常发生的 API 调用,所以我希望它尽可能高效。

4

2 回答 2

2

该答案考虑了对 Hunter Frazier 回答说您不想使用扫描的评论。

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

如果您需要执行此查询,我建议您重新访问您的架构。具体来说,我建议实施邻接列表模式,该模式在包含多对多关系的数据库中运行良好。

您可以在上面的文章中看到一些额外的注释,我在这个答案DynamoDB MM Adjacency List Design Pattern上写过

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

  • 主键:ConversationID
  • 排序键:用户 ID
  • GSI 主键:用户 ID

然后,您可以在查询中使用 GSI 主键来返回用户参与的所有对话。

于 2018-05-21T08:37:11.590 回答
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);
});
于 2018-05-21T04:27:15.967 回答