我正在设计一个 DynamoDB 架构,需要有效地满足以下用例:
获取用户按时间戳排序的前 X 条记录:
删除某个用户的所有记录:
删除用户单条记录:
如果再次提交相同数据,则更新现有记录:
record_id
,以确保相同的数据始终生成相同的 record_id
。设计A:
PK:
USER#<user_id>
SK:
RECORD#<timestamp>
优点:
缺点:
PK
和 SK
的情况下识别要删除的特定记录变得很困难。设计B:
PK:
USER#<user_id>
SK:
RECORD#<record_id>
优点:
record_id
可以轻松删除或更新单个记录。缺点:
record_id
不包含时间戳。PK:
USER#<user_id>
SK:
RECORD#<timestamp>#<record_id>
优点:
缺点:
record_id
时,复合 SK 会使查询特定记录变得复杂。我需要一个架构设计:
record_id
) 删除和更新单个记录,而不需要客户端知道确切的时间戳。如何设计一个 DynamoDB 架构来高效地满足所有这些用例?我想避免使用 GSI(因为我觉得只实现 1 个用例是一种浪费,除非确实没有办法),并且我正在寻找一种解决方案,使我能够保持前端逻辑干净,而不暴露 DynamoDB -具体细节,例如组合键(这也不是那么重要,但我认为这样更干净?)。
可以帮助我实现这一目标的最佳实践或替代方法是什么?任何指导或建议将不胜感激!
--
注意:我有一个 API,可以接收 JSON 格式的数据,我使用 sha256 对其进行哈希处理以创建该数据的唯一标识符,然后创建一个 DTO,将其发送到我的存储库,然后将数据保存到 DynamoDB,因此我的想法是,我的
ID
是在数据层之前生成的,我认为这是一个很好的做法。但即使我能够创建我的 PK&SK 作为文档的 ID,当更新并需要使用新时间戳更新文档时,它仍然会带来挑战。
是的,用户可能会多次提交相同的数据,当用户这样做时,我想做的就是保存数据,但新的时间戳会更新。
这是 NodeJs 中的一些代码,显示了我正在做的事情。
我的
controller
逻辑
const newRecord = {
v1: 'test',
v2: 'test2',
requesterUserId: '1',
};
await this.recordRepository.save({
id: sha256IdFromObj(newRecord),
timestamp: Math.floor(new Date().getTime() / 1000),
...newRecord,
}, requesterUserId);
我的
repository
逻辑
const command = new PutCommand({
TableName: this.tableName,
Item: {
pk: `USER#${userId}`,
sk: `RECORD#${queryRepoDto.id}`,
...queryRepoDto,
},
});
await this.dynamoDBDocumentClient.send(command);
以上只是表达想法的片段。
以下将起作用
主表
PK |
---|
唯一ID |
GSI
GSIPK | GSIPK |
---|---|
用户ID | 时间戳 |