如何在 CloudFormation 中使用基础架构即代码实施 DynamoDB 全局二级索引
Posted
技术标签:
【中文标题】如何在 CloudFormation 中使用基础架构即代码实施 DynamoDB 全局二级索引【英文标题】:How do I implement a DynamoDB Global Secondary Index with Infrastructure As Code in CloudFormation 【发布时间】:2019-10-29 08:01:37 【问题描述】:我正在使用基础架构即代码在 CloudFormation 中实施 GSI。我要做的就是使用这个表来记录主 DynamoTable 中的条目数。以下是主要故事的样子:
Resources:
CaseRecords:
Type: AWS::DynamoDB::Table
Properties:
TableName: $self:custom.tableName
BillingMode: PAY_PER_REQUEST
AttributeDefinitions:
- AttributeName: userId
AttributeType: S
- AttributeName: caseRecordId
AttributeType: S
KeySchema:
- AttributeName: userId
KeyType: HASH
- AttributeName: caseRecordId
KeyType: RANGE
我不需要原始表中的键,我想要的只是为新 GSI 创建一个新的 HASH 键,它会告诉我我正在跟踪的计数来自哪个表,即上面的表。
以下是迄今为止我尝试实施 GSI 的方式:
# Implement a GSI to handle item count totals
GlobalSecondaryIndexes:
- IndexName: gsiCaseCountTable
KeySchema:
- AttributeName: table-name
KeyType: HASH
ProvisionedThroughput:
ReadCapacityUnits: 5
WriteCapacityUnits: 5
但是,我得到的错误如下:
An error occurred: CaseRecords - Property Projection cannot be empty..
当我包含我的 PROJECTION 时,只有原始表中的 userId
只是为了跟踪每个用户在原始表中的条目数,我尝试以下操作:
Implement a GSI to handle item count totals
GlobalSecondaryIndexes:
- IndexName: gsiCaseCountTable
KeySchema:
- AttributeName: table-name
KeyType: HASH
Projection:
NonKeyAttributes:
- userId
ProjectionType: INCLUDE
ProvisionedThroughput:
ReadCapacityUnits: 5
WriteCapacityUnits: 5
但是这也会返回错误:
An error occurred: CaseRecords - Property AttributeDefinitions is inconsistent with the KeySchema of the table and the secondary indexes.
如何使用 CloudFormation 模板在 Dynamo 中正确实现全局二级索引,以便在原始表中记录条目数????
谢谢。
更新
如果有人想知道这就是我能够部署它的方式。这不是一个完美的解决方案,但它让我可以跟踪并计算项目表中的条目:
# NOTE: DynamoDB Serverless Configuration
# NoSQL Table for CaseRecord DB
Resources:
CaseRecords:
Type: AWS::DynamoDB::Table
Properties:
TableName: $self:custom.tableName
BillingMode: PAY_PER_REQUEST
AttributeDefinitions:
- AttributeName: userId
AttributeType: S
- AttributeName: caseRecordId
AttributeType: S
KeySchema:
- AttributeName: userId
KeyType: HASH
- AttributeName: caseRecordId
KeyType: RANGE
# Set the capacity based on the stage
# ProvisionedThroughput:
# ReadCapacityUnits: $self:custom.tableThroughput
# WriteCapacityUnits: $self:custom.tableThroughput
# Implement a GSI to handle item count totals
GlobalSecondaryIndexes:
- IndexName: gsiCaseCountTable
KeySchema:
- AttributeName: userId
KeyType: HASH
Projection:
ProjectionType: KEYS_ONLY
更新 #2 - 失败
根据下面@Pedro Arantes 提供的信息,我正在尝试使用我想要使用的属性定义来实现 GSI。然而,这也失败了。下面是实施,这里是我使用的 AWS Doc 的链接:AWS GSI Doc,这是失败的实施:
Resources:
CaseRecords:
Type: AWS::DynamoDB::Table
Properties:
TableName: $self:custom.tableName
BillingMode: PAY_PER_REQUEST
AttributeDefinitions:
- AttributeName: userId
AttributeType: S
- AttributeName: caseRecordId
AttributeType: S
- AttributeName: table-name
AttributeType: S
- AttributeName: count
AttributeType: N
KeySchema:
- AttributeName: userId
KeyType: HASH
- AttributeName: caseRecordId
KeyType: RANGE
# Set the capacity based on the stage
# ProvisionedThroughput:
# ReadCapacityUnits: $self:custom.tableThroughput
# WriteCapacityUnits: $self:custom.tableThroughput
# Implement a GSI to handle item count totals
GlobalSecondaryIndexes:
- IndexName: gsiCaseCountTable
KeySchema:
- AttributeName: table-name
KeyType: HASH
Projection:
NonKeyAttributes:
- userId
- count
ProjectionType: INCLUDE
我怎样才能让它只与我在AttributeDefinitions
中声明的NonKeyAttributes
一起工作???
【问题讨论】:
【参考方案1】:您需要在AttributeDefinitions
属性中添加table-name
。来自docs:
属性定义
描述表的键模式的属性列表和 索引。允许重复。
因此,即使您不使用原始表中的某些属性,您也必须声明能够在您的 GSI 中使用。
更新 #2 - 失败
您正在使用在AttributeDefinitions
定义为NonKeyAttributes
的键属性userId
和count
(但它们是键属性)Projection
。您不需要添加它们,因为它们是自动投影的。来自docs:
AWS::DynamoDB::表投影
表示从表中复制(投影)到索引中的属性。这些是自动投影的主键属性和索引键属性的补充。
最终模板
Resources:
CaseRecords:
Type: AWS::DynamoDB::Table
Properties:
TableName: $self:custom.tableName
BillingMode: PAY_PER_REQUEST
AttributeDefinitions:
- AttributeName: userId
AttributeType: S
- AttributeName: caseRecordId
AttributeType: S
- AttributeName: table-name
AttributeType: S
KeySchema:
- AttributeName: userId
KeyType: HASH
- AttributeName: caseRecordId
KeyType: RANGE
# Set the capacity based on the stage
# ProvisionedThroughput:
# ReadCapacityUnits: $self:custom.tableThroughput
# WriteCapacityUnits: $self:custom.tableThroughput
# Implement a GSI to handle item count totals
GlobalSecondaryIndexes:
- IndexName: gsiCaseCountTable
KeySchema:
- AttributeName: table-name
KeyType: HASH
Projection:
NonKeyAttributes:
- count
ProjectionType: INCLUDE
注意事项:
count
不应在 AttributeDefinitions
上,因为您没有将其用作密钥。
您不需要在Projection
处添加userId
,因为它会自动成为项目,因为它是在AttributeDefinitions
中定义的。
【讨论】:
所以如果我想键入一个只会增加计数器的字段,我是否必须将其作为属性包含在原始表中?我现在担心我上面完成的实现现在正在复制字段。 你介意看看我在我的问题中包含的第二个更新。即使我使用了此处文档中显示的示例,它仍然失败:docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/… 你觉得怎么样??? 您将键属性count
和 userId
添加为 NonKeyAttributes
这里是 ERROR MSG: An error occurred: CaseRecords - Property AttributeDefinitions is compatible with the KeySchema of the table and the secondary index.
我试图拥有一个名为 table-name 的 HASH 键,我只会在 GSI 中使用它。我将它添加到 AttributeDefinitions,以便可以在 GSI 中使用它。那是我想要的唯一钥匙。从那里我真的只想要 userId 并算作普通字段而不是键......我在这里哪里出错了?以上是关于如何在 CloudFormation 中使用基础架构即代码实施 DynamoDB 全局二级索引的主要内容,如果未能解决你的问题,请参考以下文章
如何在更新参数时强制 CloudFormation 堆栈更新?
如何描述 cloudformation 跨帐户堆栈信息/名称/详细信息
如何在存储桶名称中使用变量 AWS Cloudformation
通过 cloudformation 使用 aws `cdk synth` 输出