HHH*_*HHH 35 amazon-web-services nosql amazon-dynamodb
我正在尝试创建一个表来存储DynamoDB中的发票行项目.比方说,该项目是由定义CompanyCode
,InvoiceNumber
和LineItemId
,金额等行项目的详细信息.
唯一项由前3个属性的组合定义.对于不同的项目,这些属性中的任何两个都可以是相同的.我应该选择什么作为哈希属性和范围属性?
Joe*_*jr2 26
我相信@ georgeaf99提供的第一个选项不起作用,因为如果你这样做,那么CompanyCode
必须在表中是唯一的.因此,每个公司只允许一个项目.我认为第二种解决方案是唯一真正的方法.
您可以使用CompanyCode
哈希键作为哈希键,然后组合使项目唯一的所有其他字段(在这种情况下InvoiceNumber
和LineItemId
)需要以某种方式组合成一个值(例如与字段分隔符串联),这将是您的范围键.不幸的是,这有点难看,但这就是像DynamoDB这样的NoSQL数据库的本质.但是,它将允许您成功存储具有正确唯一性的记录.在回读记录时,如果您不想将组合字段解析回各个部分,那么您必须为InvoiceNumber
和添加其他单独的字段LineItemID
.
如果每个公司没有大量发票,则只能通过哈希密钥进行查询,并在客户端进行过滤.如果每个公司有大量发票并且只需要查询单个发票的项目,那么我将在CompanyCode和InvoiceNumber上创建二级索引.
aze*_*pdx 22
为了提高效率,我建议完全不同的设计.使用NoSQL数据库(和DynamoDB没有区别),我们总是需要首先考虑访问模式.此外,如果可能,我们应该努力将所有数据放在同一个表和多个索引中.根据OP和他的评论,这些是两种访问模式:
我们现在想知道什么是好主键?转换为质疑什么是好的分区键(PK)和什么是好的排序键(SK)以及我们需要创建哪些二级索引以及哪种(本地或全局)?一些提醒:
KeyConditionExpression
提供用于排序的操作符集以及介于两者之间的所有内容(其中一个是函数begins_with (a, substr)
)FilterExpression
如果您需要进一步细化查询结果(对投影属性进行过滤),您也可以使用很明显,我们正在处理需要建模并适合同一个表的多个实体.为了满足分区键在表上唯一的条件,CompanyCode
作为一个自然的分区键 - 所以我将确保它是唯一的.如果没有,那么你需要问问自己如何建模第二种访问模式?
假设我们已经在CompanyCode
let的简化上建立了唯一性并且说它以电子邮件的形式出现(或者可以是域或只是代码,但我将使用电子邮件进行演示).
CompanyCode
和SK InvoiceNumber
可以存储该公司的发票的所有属性.Customer
这使得我可以存储有关公司的所有属性.InvoiceNumber
),而我的GSI1SK是我的表PK(CompanyCode
).LineItemId
和SK正在CompanyCode
(仍然是唯一的)InvoiceNumber
,我的GSI1SK LineItemId
是表PK,因此它与Invoice实体项目相同.现在支持的访问模式:
CompanyCode=X
并使用KeyConditionExpression
与=
操作上的排序键InvoiceNumber
.如果我想获得与该发票绑定的所有项目,我将Items
使用项目属性ProjectionExpression
.BatchGetItem
API调用(使用我的唯一复合密钥LineItemId+CompanyCode
)以获取属于该特定客户的特定发票的所有项目.(这附带了BatchGetItem API的一些约束)CompanyCode=X
使用PK 进行查询并在KeyConditionExpression
SK上使用begins_with (a, substr)
函数/运算符来仅获取公司X的发票而不是该公司的元数据.这将为我提供给定公司/客户的所有发票.InvoiceNumber
我都可以轻松选择属于该特定发票的所有行项目.记住: 全局二级索引中的关键值不需要是唯一的 - 所以在我的GSI1中,我可以轻松开发invoice_1 - >(item_1,item_2),然后另一个invoice_1 - >(item_1,item_2),但两者之间存在差异GSI中的项目将在SK中(它将与不同相关联CompanyCode
(但为了演示目的,我使用了invoice_1和invoice_2).小智 8
因为我确定你已经发现你的主键(哈希+范围)不能超过两个属性.因此,根据您将要执行的查询类型和数据大小,您可以以不同方式构建表格.
(针对您在上面提到的查询类型进行了优化:仅限CompanyCode
&全部3)
适用于中小型数据集的最佳解决方案:
CompanyCode
CompanyCode
,然后在其他两个属性上过滤结果大数据集的最佳解决方案:
CompanyCode
InvoiceNumber
+LineItemId