/ #aws #cdk 

【Python】CDKでGSIを設定したDynamoDBのテーブルを作る

もくじ

AWS CDK で GSI(グローバルセカンダリインデックス)を持った DynamoDB のテーブルを作成し、AWS CLI で GSI にクエリを投げます 😊

今回の構成はこんな感じです 👍

プロジェクションタイプは追加設定が必要なINCLUDEでやってみようと思います。

前提

cdk のシリーズの続き。

プロジェクションの設定はこのあたり、

https://docs.aws.amazon.com/amazondynamodb/latest/APIReference/API_Projection.html

では 作っていきましょう 👻

requirements.txt

DynamoDB のみです 👍

aws-cdk.core==1.72.0

aws-cdk.aws_dynamodb==1.72.0

スタックファイル

メインはここですが、サンプルコードがあれば説明不要かなと思います 😅

ざっくりやってることはテーブルを新規に作り、GSI を追加してます。

追加した GSI は Index 名がHogeGSIで、テーブルとは異なるプライマリーキーgsi_pk, gsi_skを持ち、 projection_param_a, projection_param_bがプロジェクションされる設定です 👍

from aws_cdk import core
from aws_cdk.aws_dynamodb import Attribute, AttributeType, ProjectionType, Table


class DynamoTableGsiStack(core.Stack):
    def __init__(self, scope: core.Construct, id: str, **kwargs) -> None:
        super().__init__(scope, id, **kwargs)

        table = Table(
            self,
            "DynamoTableGsiTable",
            partition_key=Attribute(name="pk", type=AttributeType.NUMBER),
            sort_key=Attribute(name="sk", type=AttributeType.STRING),
        )

        table.add_global_secondary_index(
            index_name="HogeGSI",
            partition_key=Attribute(name="gsi_pk", type=AttributeType.NUMBER),
            sort_key=Attribute(name="gsi_sk", type=AttributeType.STRING),
            projection_type=ProjectionType.INCLUDE,
            non_key_attributes=["projection_param_a", "projection_param_b"],  # INCLUDEでプロジェクションするアトリビュート
        )

エントリーポイントへ追記

下記を追加

...
from stacks.dynamo_table_gsi_stack import DynamoTableGsiStack
...
DynamoTableGsiStack(app, "dynamo-table-gsi-stack", env=env)
...

デプロイ

$ cdk deploy dynamo-table-gsi-stack

動作確認

作ったテーブルの名前を取得します。

$ aws dynamodb list-tables | grep dynamo-table-gsi-stack

今回はこんな(↓)名前でした。

dynamo-table-gsi-stack-DynamoTableGsiTable3CEEAFD7-ZBM15Z9CA40P

テーブルの詳細を確認して GSI が作られていることを確認します

ちょっと長いですね 😅

$ TABLE_NAME=dynamo-table-gsi-stack-DynamoTableGsiTable3CEEAFD7-ZBM15Z9CA40P
$ aws dynamodb describe-table --table-name $TABLE_NAME
{
    "Table": {
        "AttributeDefinitions": [
            {
                "AttributeName": "gsi_pk",
                "AttributeType": "N"
            },
            {
                "AttributeName": "gsi_sk",
                "AttributeType": "S"
            },
            {
                "AttributeName": "pk",
                "AttributeType": "N"
            },
            {
                "AttributeName": "sk",
                "AttributeType": "S"
            }
        ],
        "TableName": "dynamo-table-gsi-stack-DynamoTableGsiTable3CEEAFD7-ZBM15Z9CA40P",
        "KeySchema": [
            {
                "AttributeName": "pk",
                "KeyType": "HASH"
            },
            {
                "AttributeName": "sk",
                "KeyType": "RANGE"
            }
        ],
        "TableStatus": "ACTIVE",
        "CreationDateTime": xxxxxxxxxx.xxx,
        "ProvisionedThroughput": {
            "NumberOfDecreasesToday": 0,
            "ReadCapacityUnits": 5,
            "WriteCapacityUnits": 5
        },
        "TableSizeBytes": 0,
        "ItemCount": 0,
        "TableArn": "arn:aws:dynamodb:xxxxxxxxxxxxxx:xxxxxxxxxxxx:table/dynamo-table-gsi-stack-DynamoTableGsiTable3CEEAFD7-ZBM15Z9CA40P",
        "TableId": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
        "GlobalSecondaryIndexes": [
            {
                "IndexName": "HogeGSI",
                "KeySchema": [
                    {
                        "AttributeName": "gsi_pk",
                        "KeyType": "HASH"
                    },
                    {
                        "AttributeName": "gsi_sk",
                        "KeyType": "RANGE"
                    }
                ],
                "Projection": {
                    "ProjectionType": "INCLUDE",
                    "NonKeyAttributes": [
                        "projection_param_b",
                        "projection_param_a"
                    ]
                },
                "IndexStatus": "ACTIVE",
                "ProvisionedThroughput": {
                    "NumberOfDecreasesToday": 0,
                    "ReadCapacityUnits": 5,
                    "WriteCapacityUnits": 5
                },
                "IndexSizeBytes": 0,
                "ItemCount": 0,
                "IndexArn": "arn:aws:dynamodb:xxxxxxxxxxxxxx:xxxxxxxxxxxx:table/dynamo-table-gsi-stack-DynamoTableGsiTable3CEEAFD7-ZBM15Z9CA40P/index/HogeGSI"
            }
        ]
    }
}

ちゃんと設定された、、、ようですが、一応動きを確認しておきましょうか(笑)

# ダミーのデータを入れてみる
$ aws dynamodb put-item \
  --table-name $TABLE_NAME \
  --item '{"pk":{"N":"1234"},"sk":{"S":"hogehoge"},"gsi_pk":{"N":"987"},"gsi_sk":{"S":"hugohugo"},"projection_param_a":{"S":"HOGEHOGE"},"projection_param_b":{"S":"HUGOHUGO"},"dummy_param":{"S":"このアトリビュートはGSIでは取得されない"}}'

# テーブルにquery
$ aws dynamodb query \
    --table-name $TABLE_NAME \
    --key-condition-expression "pk =:v1" \
    --expression-attribute-values '{":v1":{"N":"1234"}}'
{
    "Items": [
        {
            "gsi_pk": {
                "N": "987"
            },
            "gsi_sk": {
                "S": "hugohugo"
            },
            "projection_param_b": {
                "S": "HUGOHUGO"
            },
            "projection_param_a": {
                "S": "HOGEHOGE"
            },
            "dummy_param": {
                "S": "このアトリビュートはGSIでは取得されない"
            },
            "sk": {
                "S": "hogehoge"
            },
            "pk": {
                "N": "1234"
            }
        }
    ],
    "Count": 1,
    "ScannedCount": 1,
    "ConsumedCapacity": null
}

# Indexにquery
$ aws dynamodb query \
    --table-name $TABLE_NAME \
    --index-name HogeGSI \
    --key-condition-expression "gsi_pk =:v1" \
    --expression-attribute-values '{":v1":{"N":"987"}}'
{
    "Items": [
        {
            "gsi_pk": {
                "N": "987"
            },
            "sk": {
                "S": "hogehoge"
            },
            "pk": {
                "N": "1234"
            },
            "gsi_sk": {
                "S": "hugohugo"
            },
            "projection_param_b": {
                "S": "HUGOHUGO"
            },
            "projection_param_a": {
                "S": "HOGEHOGE"
            }
        }
    ],
    "Count": 1,
    "ScannedCount": 1,
    "ConsumedCapacity": null
}

テーブルにも GSI にも query が通ることが確認できました 👍

プロジェクションした param も取得できてます。

デストロイ

$ cdk destroy dynamo-table-gsi-stack

まとめ

CDK で GSI を持った Dynamo のテーブルを作り、cli 経由で query を投げて動作確認をしました 👍

今回のリポジトリはこちら

https://github.com/sisi100/cdk-my-template/tree/20201226.1

Author

Sisii

インフラが好きなエンジニアぶってるなにか