你在这里有一个多对多的关系。一个文件夹可以有多个文档,一个文档可以位于多个文件夹中。没有一种方法可以对这些类型的关系进行建模,因为它们往往是特定于应用程序的并且高度依赖于您的访问模式。既然是这种情况,我将需要对您的应用程序做出一些假设来回答您的问题。我会尽量说明我在哪里以及关于我的假设。
一般来说,使用 NoSQL,您可以设计模式并组织数据以支持应用程序中的特定视图。很多时候这涉及到数据的非规范化,特别是在多对多关系的情况下,这就是为什么这些类型的关系的策略往往如此特定于应用程序的原因。
在下面的示例中,我将假设您有某种主从视图,其中主列表包含子文件夹和特定文件夹中文档的摘要信息,详细视图显示有关当前选定文档的所有信息.
模式
首先,我将根据上面的模式定义模式,但稍作修改以更适合 DynamoDB。
文件夹
{
"id": String,
"parent_id": String,
"name": String,
}
文档
{
"id": String,
"title": String,
"contents": String,
"date_modified": String,
"date_uploaded": String,
}
Document 模型很容易解释。此外,我们将创建一个 DocumentSummary,其中仅包含有关文档的摘要信息。
文件摘要
{
"id": String,
"parent_id": String,
"title": String,
"date_uploaded": String,
}
根据经验,DocumentSummary 模型应该是 Document 模型的子集,并且只包含不可变的字段,例如date_uploaded
,或者变化非常缓慢的字段,例如title
。诸如date_modified
可能会非常迅速地发生变化的字段可能会导致问题(我们稍后会看到原因)。此外,诸如此类的字段contents
不应进入我们的摘要模型。除了contents
是一个快速静音的领域之外,它没有任何“总结”。请记住,我们的汇总模型越接近我们的完整模型,我们的汇总模型就越没用。在某些时候,我们不妨抛弃我们的汇总模型,只使用我们的完整模型。
表
我们将有两个表,DocumentTable 和 DirectoryTable。
文档表
Hash Key: "id"
DocumentTable 包含我们的文档并为我们提供执行 CRUD 操作的能力id
目录表
Hash Key: "parent_id"
Sort Key: "id"
DirectoryTable 将包含文件夹和 DocumentSummaries。由于此表包含两种不同的类型,因此每种类型的 ID 不能发生冲突非常重要。我建议在您的 ID 前加上命名空间,例如“folder-123”和“document-123”。
DirectoryTable 使我们能够查询给定文件夹中的所有子文件夹和文档摘要,并允许我们通过parent_id
和更新文件夹和 DocumentSummaries id
。
例如,如果我们想在“folder-123”中查找所有子文件夹和文档摘要,我们可以使用以下参数查询。
{
"TableName": "DirectoryTable",
"KeyConditionExpression": "parent_id = :parent_id",
"ExpressionAttributeValues": {
":parent_id": {"S": "folder-123"},
}
}
注意:对于顶级文件夹和文档,您需要使用parent_id
“root”等虚拟对象
此外,我们可能想要查询特定文档所在的文件夹。要回答这个问题,我们需要在 DirectoryTable 上创建一个全局二级索引 (GSI)
id-parent_id-index(目录表 GSI)
Hash Key: "id"
Sort Key: "parent_id"
现在,我们可以使用带有以下参数的 Query 来查找 ID 为“document-123”的文档的所有父文件夹 ID。
{
"TableName": "DirectoryTable",
"IndexName": "id-parent_id-index",
"KeyConditionExpression": "id = :id",
"ExpressionAttributeValues": {
":id": {"S": "document-123"}
}
}
您可能想知道如何通过id
. 您可以使用id-parent_id-index
与上述相同的查询参数再次使用,将“document-123”替换为文件夹 ID,例如“folder-123”。如果你做对了,这应该会产生一个长度为 1 的 Items 数组。
最后,我们需要一种方法来更新 DocumentSummaries,当其中一个重复字段在相应的 Document 上更新时。我们可以为此使用 DynamoDB Streams。在 DocumentTable 上创建一个 DynamoDB Stream 并监听更新事件。如果更新事件指示重复字段之一已被修改,请使用查找 Document 的所有父文件夹,然后通过和id-parent_id-index
更新 DocumentSummary 。此更新可能非常昂贵,因为它是扇出问题的一个示例,例如,单个 Document 更新会导致 N DocumentSummary 更新。最小化这个成本很重要,特别是在大规模时,这就是为什么我们只想在 DocumentSummary 中包含不可变或缓慢变化的字段。parent_id
id