我正在尝试创建一个表,以便在 DynamoDB 中存储发票行项目。假设项目由 CompanyCode、 InvoiceNumber和 LineItemId、金额和其他项目细节定义。
CompanyCode
InvoiceNumber
LineItemId
一个唯一的项目是由前3个属性的组合定义的。这些属性中的任何两个对于不同的项目都是相同的。我应该选择什么作为散列属性和范围属性?
我相信您已经发现,主键(hash + range)的属性不能超过两个。因此,根据要执行的查询类型和数据大小,您可以以不同的方式构造表。
(针对上面提到的查询类型进行了优化: 只有 CompanyCode和所有3)
适用于中小型数据集的最佳溶胶:
大型数据集的最佳解决方案:
我相信 @ georgeaf99提供的第一个选项不会起作用,因为如果你这样做,那么 CompanyCode在表中必须是唯一的。因此,每个公司只允许有一个项目。我认为第二个解决方案是唯一可行的方法。
您可以使用 CompanyCode作为散列键,然后所有其他字段组合起来使项目唯一(在本例中为 InvoiceNumber和 LineItemId)需要以某种方式为 合并成一个值(例如与字段分隔符连接) ,这将是您的范围键。不幸的是,这有点难看,但这就是像 DynamoDB 这样的 NoSQL 数据库的本质。但是,它将允许您以正确的唯一性成功地存储记录。在返回读取记录时,如果不想将合并后的字段解析回它的各个部分,那么必须为 InvoiceNumber和 LineItemID添加额外的单独字段。
LineItemID
如果每个公司没有大量的发票,那么只能通过 Hash 键进行查询,并在客户端进行过滤。如果每个公司有大量的发票,并且只需要查询单个发票的项目,那么我将在 CompanyCode 和 InvoiceNumber 上创建一个辅助索引。
为了提高效率,我建议采用完全不同的设计。对于 NoSQL 数据库(DynamoDB 也不例外) ,我们总是需要首先考虑访问模式。此外,如果可能的话,我们应该努力将所有数据放在同一个表和几个索引中。从 OP 和他的评论来看,有两种访问模式:
我们现在想知道什么是好的主键?转换为问题什么是一个好的分区键(PK) ,什么是一个好的排序键(SK) ,我们需要创建哪些辅助索引,以及什么类型(本地或全局) ?一些提醒:
KeyConditionExpression
begins_with (a, substr)
FilterExpression
很明显,我们正在处理多个需要建模并放入同一个表中的实体。为了满足 Partition Key 在表中是唯一的条件,CompanyCode作为一个天然的 Partition Key 出现——所以我将确保它是唯一的。如果没有,那么您需要问自己如何建模第二种访问模式?
假设我们已经在 CompanyCode上建立了唯一性,让我们简化一下,假设它是以电子邮件的形式出现的(或者可以是域或者仅仅是代码,但是我将使用电子邮件进行演示)。
我建议设计如下图所示:
Customer
现在支持的访问模式如下:
CompanyCode=X
=
Items
ProjectionExpression
BatchGetItem
LineItemId+CompanyCode