AWS CLIでGSIやLSIを持つDynamoDBテーブルを作成しようとしたらハマった話
こんにちは、CX事業本部の若槻です。
前回の記事ではマネジメントコンソールからGSIおよびLSIを持つDynamoDBテーブルの作成を行いました。
次に、AWS CLIでGSIやLSIを持つDynamoDBテーブルを作成しようとしたのですが、正常に作成できるまでにトライ&エラーを繰り返すハメになったので、今回はその際の記録をメモとして残させていただきます。
ハマった際の記録
GSIを持つテーブルの作成
dynamodb create-table
コマンドでglobal-secondary-indexes
オプションを指定してGSIを持つテーブルを作成しようと次のようなコマンドを作成し、実行しました。
$ aws dynamodb create-table \
--table-name Object \
--attribute-definitions \
AttributeName=objectType,AttributeType=S \
--key-schema \
AttributeName=objectType,KeyType=HASH \
--provisioned-throughput \
ReadCapacityUnits=5,WriteCapacityUnits=5 \
--global-secondary-indexes \
IndexName=GSI-objectId,KeySchema=[{AttributeName=objectId,KeyType=HASH}],Projection={ProjectionType=ALL}
すると以下のエラーとなりました。
Parameter validation failed:
Invalid type for parameter GlobalSecondaryIndexes```0.KeySchema```0, value: AttributeName=objectId, type: <class 'str'>, valid types: <class 'dict'>
Invalid type for parameter GlobalSecondaryIndexes```1.KeySchema```0, value: KeyType=HASH, type: <class 'str'>, valid types: <class 'dict'>
ググって見つけたサイトによると{AttributeName=objectId,KeyType=HASH}
をクォートで囲む必要があるとのことです。
そこでコマンドを次のように修正して実行しました。
$ aws dynamodb create-table \
--table-name Object \
--attribute-definitions \
AttributeName=objectType,AttributeType=S \
--key-schema \
AttributeName=objectType,KeyType=HASH \
--provisioned-throughput \
ReadCapacityUnits=5,WriteCapacityUnits=5 \
--global-secondary-indexes \
IndexName=GSI-objectId,KeySchema=[{'AttributeName=objectId,KeyType=HASH'}],Projection={ProjectionType=ALL}
すると次は以下のエラーとなりました。
An error occurred (ValidationException) when calling the CreateTable operation: One or more parameter values were invalid: ProvisionedThroughput is not specified for index: GSI-objectId
global-secondary-indexes
オプションでもProvisionedThroughput
を指定する必要があるとのことです。GUIからGSIありのテーブルを作成した時はProvisionedThroughputを明示的に指定する必要はなかったため、CLIでも不要だと思い込んでいました。
そこでコマンドを次のように修正して実行しました。
$ aws dynamodb create-table \
--table-name Object \
--attribute-definitions \
AttributeName=objectType,AttributeType=S \
--key-schema \
AttributeName=objectType,KeyType=HASH \
--provisioned-throughput \
ReadCapacityUnits=5,WriteCapacityUnits=5 \
--global-secondary-indexes \
IndexName=GSI-objectId,KeySchema=[{'AttributeName=objectId,KeyType=HASH'}],Projection={ProjectionType=ALL},ProvisionedThroughput={ReadCapacityUnits=5,WriteCapacityUnits=5}
次は以下のようなエラーとなりました。
Parameter validation failed:
Invalid type for parameter GlobalSecondaryIndexes```0.ProvisionedThroughput, value: ReadCapacityUnits=5, type: <class 'str'>, valid types: <class 'dict'>
Invalid type for parameter GlobalSecondaryIndexes```1.ProvisionedThroughput, value: WriteCapacityUnits=5, type: <class 'str'>, valid types: <class 'dict'>
どうやらProvisionedThroughput
の値もクォートで囲む必要がありそうです。
そこでコマンドを次のように修正して実行しました。
$ aws dynamodb create-table \
--table-name Object \
--attribute-definitions \
AttributeName=objectType,AttributeType=S \
--key-schema \
AttributeName=objectType,KeyType=HASH \
--provisioned-throughput \
ReadCapacityUnits=5,WriteCapacityUnits=5 \
--global-secondary-indexes \
IndexName=GSI-objectId,KeySchema=[{'AttributeName=objectId,KeyType=HASH'}],Projection={ProjectionType=ALL},ProvisionedThroughput='{ReadCapacityUnits=5,WriteCapacityUnits=5}'
次は以下のようなエラーとなりました。
An error occurred (ValidationException) when calling the CreateTable operation: One or more parameter values were invalid: Some index key attributes are not defined in AttributeDefinitions. Keys: ```objectId, AttributeDefinitions: ```objectType
GSIで使用するキーもattribute-definitions
で指定する必要があるようです。
そこでコマンドを次のように修正して実行しました。
$ aws dynamodb create-table \
--table-name Object \
--attribute-definitions \
AttributeName=objectType,AttributeType=S \
AttributeName=objectId,AttributeType=S \
--key-schema \
AttributeName=objectType,KeyType=HASH \
--provisioned-throughput \
ReadCapacityUnits=5,WriteCapacityUnits=5 \
--global-secondary-indexes \
IndexName=GSI-objectId,KeySchema=[{'AttributeName=objectId,KeyType=HASH'}],Projection={ProjectionType=ALL},ProvisionedThroughput='{ReadCapacityUnits=5,WriteCapacityUnits=5}'
コマンドが正常に実行でき、GSIを持つテーブルを作成できました。
LSIを持つテーブルの作成
dynamodb create-table
コマンドでlocal-secondary-indexes
オプションを指定してLSIを持つテーブルを作成しようと次のようなコマンドを作成し、実行しました。
$ aws dynamodb create-table \
--table-name Object \
--attribute-definitions \
AttributeName=objectType,AttributeType=S \
AttributeName=updatedAt,AttributeType=N \
--key-schema \
AttributeName=objectType,KeyType=HASH \
--provisioned-throughput \
ReadCapacityUnits=5,WriteCapacityUnits=5 \
--local-secondary-indexes \
IndexName=LSI-objectType,KeySchema=['{AttributeName=objectType,KeyType=HASH}','{AttributeName=updatedAt,KeyType=RANGE}'],Projection={ProjectionType=ALL}
すると以下のようなエラーとなりました。
An error occurred (ValidationException) when calling the CreateTable operation: One or more parameter values were invalid: Table KeySchema does not have a range key, which is required when specifying a LocalSecondaryIndex
LSIを持たせるテーブルにはプライマリソートキーを指定する必要があるようです。
そこでコマンドを次のように修正して実行しました。
$ aws dynamodb create-table \
--table-name Object \
--attribute-definitions \
AttributeName=objectType,AttributeType=S \
AttributeName=createdAt,AttributeType=N \
AttributeName=updatedAt,AttributeType=N \
--key-schema \
AttributeName=objectType,KeyType=HASH \
AttributeName=createdAt,KeyType=RANGE \
--provisioned-throughput \
ReadCapacityUnits=5,WriteCapacityUnits=5 \
--local-secondary-indexes \
IndexName=LSI-objectType,KeySchema=['{AttributeName=objectType,KeyType=HASH}','{AttributeName=updatedAt,KeyType=RANGE}'],Projection={ProjectionType=ALL}
コマンドが正常に実行でき、LSIを持つテーブルを作成できました。
GSIとLSIを持つテーブルの作成
LSIのパーティションキーに、プライマリではなくGSIのパーティションキーを指定できるのか気になったので確認してみました。
dynamodb create-table
コマンドでlocal-secondary-indexes
とglobal-secondary-indexes
オプションを指定して、LSIとGSIを持つテーブルを作成しようと次のようなコマンドを作成し、実行しました。
$ aws dynamodb create-table \
--table-name Object \
--attribute-definitions \
AttributeName=objectType,AttributeType=S \
AttributeName=objectId,AttributeType=S \
AttributeName=createdAt,AttributeType=N \
AttributeName=updatedAt,AttributeType=N \
--key-schema \
AttributeName=objectType,KeyType=HASH \
AttributeName=createdAt,KeyType=RANGE \
--provisioned-throughput \
ReadCapacityUnits=5,WriteCapacityUnits=5 \
--global-secondary-indexes \
IndexName=GSI-objectId,KeySchema=["{AttributeName=objectId,KeyType=HASH}"],Projection={ProjectionType=ALL},ProvisionedThroughput="{ReadCapacityUnits=5,WriteCapacityUnits=5}" \
--local-secondary-indexes \
IndexName=LSI-objectType,KeySchema=["{AttributeName=objectId,KeyType=HASH}","{AttributeName=updatedAt,KeyType=RANGE}"],Projection={ProjectionType=ALL}
すると次のようなエラーとなりました。
An error occurred (ValidationException) when calling the CreateTable operation: One or more parameter values were invalid: Index KeySchema does not have the same leading hash key as table KeySchema for index: LSI-objectType. index hash key: objectId, table hash key: objectType
LSIのパーティションキーにはプライマリと同じ属性を指定する必要があるようです。
LSIのパーティションキーにプライマリと同じ属性を指定するようにコマンドを修正し、実行してみます。
$ aws dynamodb create-table \
--table-name Object \
--attribute-definitions \
AttributeName=objectType,AttributeType=S \
AttributeName=objectId,AttributeType=S \
AttributeName=createdAt,AttributeType=N \
AttributeName=updatedAt,AttributeType=N \
--key-schema \
AttributeName=objectType,KeyType=HASH \
AttributeName=createdAt,KeyType=RANGE \
--provisioned-throughput \
ReadCapacityUnits=5,WriteCapacityUnits=5 \
--global-secondary-indexes \
IndexName=GSI-objectId,KeySchema=["{AttributeName=objectId,KeyType=HASH}"],Projection={ProjectionType=ALL},ProvisionedThroughput="{ReadCapacityUnits=5,WriteCapacityUnits=5}" \
--local-secondary-indexes \
IndexName=LSI-objectType,KeySchema=["{AttributeName=objectType,KeyType=HASH}","{AttributeName=updatedAt,KeyType=RANGE}"],Projection={ProjectionType=ALL}
コマンドが正常に実行でき、テーブルを作成できました。
おわりに
AWS CLIでGSIやLSIを持つDynamoDBテーブルを作成しようとしたらハマった話のご紹介でした。
そういえば最近あまりAWS CLIを触れてなかったのでもっとちゃんと触ろうと思いました。
参考
- aws . dynamodb create-table | AWS CLI Command Reference
- DynamoDB の使用開始 ステップ 6: グローバルセカンダリインデックスを作成する | Amazon DynamoDB 開発者ガイド
- How to Create Dynamodb Global Secondary Index using AWS CLI? | stack overflow
以上