DynamoDB 好友查询

DynamoDB Friends Query

我有 DynamoDB table 用户,friends.Schema 看起来很糟糕。这里用户1(tom)和用户2(rob)是朋友。

+--------+---------+----------+
|   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. 是否可以在一次查询中获取用户 1 (tom) 的朋友姓名?
  2. 如果不是,什么是有效的查询方式。

任何帮助将不胜感激。

我目前在做的是:

第 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();
}

DynamoDB 中的数据建模需要一种不同于使用 SQL 数据库时可能使用的思维方式。要充分利用 DynamoDB,您需要考虑您的应用程序访问模式并以支持这些用例的方式存储您的数据。

听起来您的访问模式是“通过用户 ID 获取好友”。有多种方法可以实现此访问模式,但我将向您提供一些关于如何实现它的想法。

想法 1:对数据进行非规范化

您可以创建一个 list 属性并存储每个用户的好友列表。这将使用户获取朋友超级简单!

与任何访问模式一样,这种方法也有局限性。 DynamoDB 属性的最大大小为 400KB,因此您只能使用该大小的好友列表。此外,您将无法根据该属性的值执行查询,因此它不支持其他访问模式。但是,它超级简单!

想法 2:构建项目集合,将朋友存储在 USER#<id> 分区中。

这是在 DynamoDB 中表示 one-to-many 关系的典型模式。假设您使用 USER#<user_id> 的 PK 和 FRIEND#<friend_id> 的 SK 来定义友谊。您的 table 将如下所示:

您可以通过在用户分区键中搜索 begins_with FRIEND 的排序键来获取给定用户的好友。

这只是两个想法,在 DynamoDB 中还有更多(并且可能更好)的方式来模拟友谊。我给出的示例将这种关系视为 one-to-many(一个用户有很多朋友)。更有可能的是您与模型有 many-to-many 关系,这在 DynamoDB 中可能很棘手(完全是另一个主题!)

如果 many-to-many 听起来像您所拥有的,AWS 有一个 article describing modeling many-to-many 关系可以证明是一个很好的起点。