我正在尝试创建一个表来存储DynamoDB中的发票行项目。我们假设该项目由CompanyCode
,InvoiceNumber
和LineItemId
,金额和其他订单项详细信息定义。
唯一项目由前3个属性的组合定义。对于不同的项目,这些属性中的任何两个都可以是相同的。我应该选择什么作为哈希属性和范围属性?
答案 0 :(得分:21)
我相信the first option offered by @georgeaf99不起作用,因为如果你这样做,那么CompanyCode
必须在表格中是唯一的。因此,每个公司只允许一个项目。我认为第二种解决方案是唯一真正的方法。
您可以使用CompanyCode
作为哈希键,然后结合使项目唯一的所有其他字段(在本例中为InvoiceNumber
和LineItemId
)需要以某种方式合并为一个值(例如与字段分隔符串联),这将是您的范围键。不幸的是,这有点难看,但这就是像DynamoDB这样的NoSQL数据库的本质。但是,它将允许您成功存储具有正确唯一性的记录。回读记录时,如果您不想将组合字段解析回各个部分,则必须为InvoiceNumber
和LineItemID
添加其他单独的字段。
如果每个公司没有大量发票,则只能通过哈希密钥进行查询,并在客户端进行过滤。如果每个公司有大量发票并且只需要查询单个发票的项目,那么我将在CompanyCode和InvoiceNumber上创建二级索引。
答案 1 :(得分:11)
为了提高效率,我会提出完全不同的设计。对于NoSQL数据库(和DynamoDB没什么不同),我们始终需要首先考虑访问模式。另外,如果可能的话,我们应努力将所有数据放入同一张表和多个索引中。从OP和他的评论中可以得出,这是两种访问模式:
我们现在想知道什么是好的主键?转换为疑问,什么是好的分区键(PK),什么是好的排序键(SK),我们需要创建哪些二级索引,以及哪种类型的二级索引(本地或全局)?一些提醒:
KeyConditionExpression
,该选项为您提供set of operators for sorting及其之间的所有内容(其中之一是功能begins_with (a, substr)
)FilterExpression
很明显,我们正在处理需要建模并适合同一张表的多个实体。为了满足分区键在表上唯一的条件,CustomerCode
是自然的分区键-因此,我将确保其唯一。如果不是,那么您需要问自己:如何为第二种访问模式建模?
假设我们已经在CompanyCode
上建立了唯一性,我们可以简化说,它以电子邮件的形式出现(或者可以是域,也可以是代码,但我将使用电子邮件进行演示)。 / p>
CompanyCode
,SK为InvoiceNumber
,则可以存储该公司有关该发票的所有属性。Customer
的记录,这使我可以存储有关公司的所有属性。 InvoiceNumber
),而我的GSI1SK是我的表PK(CompanyCode
)。LineItemId
,SK为CompanyCode
(仍然是唯一的)InvoiceNumber
,我的GSI1SK为LineItemId
,这是表PK,因此与“发票”实体项目相同。现在支持以下访问模式:
CompanyCode=X
,并在排序键上将KeyConditionExpression
与=
运算符一起使用InvoiceNumber
。如果要获取与该发票相关的所有项目,我将使用Items
投影ProjectionExpression
属性。 BatchGetItem
API调用(使用我的唯一组合键LineItemId+CompanyCode
)以获取属于该项目的所有项目该特定客户的特定发票。 (这带有BatchGetItem API的一些限制)CompanyCode=X
进行查询,并在SK上将KeyConditionExpression
函数/运算符与begins_with (a, substr)
一起使用,以仅获取公司X的发票,而不获取公司X的发票有关该公司的元数据。这将为我提供给定公司/客户的所有发票。InvoiceNumber
,我都可以轻松地选择属于该特定发票的所有行项目。 记住: The key values in a global secondary index do not need to be unique-因此,在我的GSI1中,我可以很容易地开具发票_1->(项目_1,item_2),然后又有另一个发票_1->(项目_1,item_2),但是GSI将位于SK中(它将与不同的CompanyCode
相关联(但出于演示目的,我使用了invoice_1和invoice_2)。答案 2 :(得分:7)
我确定你已经发现你的主键(哈希+范围)不能超过两个属性。因此,根据您要执行的查询类型和数据大小,您可以采用不同的方式构建表格。
(针对您上面提到的查询类型进行了优化:仅CompanyCode
&全部3)
适用于中小型数据集的最佳解决方案:
CompanyCode
CompanyCode
和执行查询
然后根据其他两个属性过滤结果大数据集的最佳解决方案:
CompanyCode
InvoiceNumber
+ LineItemId