この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。
はじめに
サーバーレス開発部の藤井元貴です。
DynamoDBのレビュー会があり、そこで面白い使い方を知ったのでご紹介します。
実際に使う場合は、DynamoDBの設計をしっかりと実施してください。
ちなみに、DynamoDBのベストプラクティスはこちらです。
AWS公式が公開している資料も参考になると思います。
おすすめの方
- DynamoDBに興味がある
- AWS SAM(CloudFormation)でDynamoDBを使いたい
- AWS SAMでPathパラメータを使うAPIを作りたい
DynamoDBの面白い使い方
DynamoDBのユニークなKeyに対して、エイリアスレコード(別名用)を用意します。(エイリアスレコードは公式名称ではなく、勝手につけた名称です)
これにより、「Keyの表記ゆらぎ」があっても、DynamoDB内のレコードを特定できます!!
たとえば?
次のようなWebAPIがあるとします。
Path | Method |
---|---|
/color/{param} | GET |
この{param}
に対して、次のように異なるモノ(色名と色コード)を与えても、同じJSONを返却するように実装したいです。
- color/red
- color/ff0000
{
"name":"red",
"name_ja":"赤",
"r":255,
"g":0,
"b":0
}
red
やff0000
をそれぞれKeyとして、DynamoDBに同じ情報を持つのは無駄です。
name (Hash Key) | name_ja | r | g | b |
---|---|---|---|---|
red | 赤 | 255 | 0 | 0 |
ff0000 | 赤 | 255 | 0 | 0 |
そこで、DynamoDBのテーブルを次のように設計し、エイリアスレコード(別名用)を設けます。
name (Hash Key) | reference | name_ja | r | g | b |
---|---|---|---|---|---|
red | 赤 | 255 | 0 | 0 | |
ff0000 | red |
これにより、次の動作を行えば、「red」と「ff0000」で同じ内容を返却できます。
/color/red
の場合は、redを取得して返却する/color/ff0000
の場合は、ff0000を取得し、referenceを参照し、redを取得して返却する
目から鱗が落ちました。
エイリアスレコード以外の全データ取得は?
reference
以外の項目にGSI(グローバル・セカンダリ・インデックス)を設定すると取得できます。
今回はname_ja
にGSIを設定しています。
やってみた
環境
項目 | バージョン |
---|---|
macOS | High Sierra 10.13.6 |
AWS CLI | aws-cli/1.16.89 Python/3.6.1 Darwin/17.7.0 botocore/1.12.79 |
AWS SAM CLI | 0.10.0 |
Python | 3.6 |
サーバーレスなアプリの作成
AWS SAMを使用して作成します。
プロジェクトフォルダの作成
sam init --runtime python3.6 --name TryDynamoDB
Lambda関数とtemplateファイル
app.pyとtemplate.yamlは下記です。
見にくいですが、下記を一度に返却しています。
- pathで指定した1つのレコード
- 全てのレコード(エイリアスレコードを除く)
S3バケットの作成
コード等を格納するためのS3バケットを作成します。作成済みの場合は飛ばします。
aws s3 mb s3://cm-fujii.genki-sam-test-bucket
build
下記でビルドします。
sam build
package
コード一式をS3バケットにアップロードします。
sam package \
--output-template-file packaged.yaml \
--s3-bucket cm-fujii.genki-sam-test-bucket
deploy
デプロイします。
sam deploy \
--template-file packaged.yaml \
--stack-name TryDynamoDB \
--capabilities CAPABILITY_IAM
動作確認
DynamoDBのテーブルにItemを追加
まずはparam=name
のItemを追加します。
aws dynamodb put-item \
--table-name TryDynamoDB-ColorTable \
--item '{"name":{"S":"red"}, "name_ja":{"S":"赤"}, "r":{"N":"255"}, "g":{"N":"0"}, "b":{"N":"0"}}'
aws dynamodb put-item \
--table-name TryDynamoDB-ColorTable \
--item '{"name":{"S":"green"}, "name_ja":{"S":"緑"}, "r":{"N":"0"}, "g":{"N":"255"}, "b":{"N":"0"}}'
aws dynamodb put-item \
--table-name TryDynamoDB-ColorTable \
--item '{"name":{"S":"blue"}, "name_ja":{"S":"青"}, "r":{"N":"0"}, "g":{"N":"0"}, "b":{"N":"255"}}'
続いて、param=rgb
のItemを追加します。
aws dynamodb put-item \
--table-name TryDynamoDB-ColorTable \
--item '{"name":{"S":"ff0000"}, "reference":{"S":"red"}}'
aws dynamodb put-item \
--table-name TryDynamoDB-ColorTable \
--item '{"name":{"S":"00ff00"}, "reference":{"S":"green"}}'
aws dynamodb put-item \
--table-name TryDynamoDB-ColorTable \
--item '{"name":{"S":"0000ff"}, "reference":{"S":"blue"}}'
こうなりました。
WebAPIのエンドポイントを確認
Web画面ポチポチでも良いですが、せっかくなのでコマンドを使います。
$ aws cloudformation describe-stacks --stack-name TryDynamoDB --query 'Stacks[].Outputs'
[
[
{
"OutputKey": "HelloWorldApi",
"OutputValue": "https://xxxxxxxxxx.execute-api.ap-northeast-1.amazonaws.com/Prod/color/{param}",
"Description": "API Gateway endpoint URL for Prod stage for Hello World function"
}
]
]
OutputValue
がWebAPIのエンドポイントです!
いざ、確認!
まずは、param=name
を確認します。
curl https://xxxxxxxxxx.execute-api.ap-northeast-1.amazonaws.com/Prod/color/red
結果はこちら。red
が取得できました。(\u8d64は「赤」です)
ついでに、「実体レコードのみ(3個)」も取得できました!
{
"get_item":{
"r":255,
"b":0,
"name":"red",
"name_ja":"\u8d64",
"g":0
},
"scan":[
{
"r":255,
"b":0,
"name":"red",
"g":0,
"name_ja":"\u8d64"
},
{
"r":0,
"b":0,
"name":"green",
"g":255,
"name_ja":"\u7dd1"
},
{
"r":0,
"b":255,
"name":"blue",
"g":0,
"name_ja":"\u9752"
}
]
}
続いて、param=rgb
を確認します。
curl https://xxxxxxxxxx.execute-api.ap-northeast-1.amazonaws.com/Prod/color/ff0000
結果はこちら。red
が取得できました。(\u8d64は「赤」です)
同じ内容ですね!!
{
"get_item":{
"r":255,
"b":0,
"name":"red",
"name_ja":"\u8d64",
"g":0
},
"scan":[
{
"r":255,
"b":0,
"name":"red",
"g":0,
"name_ja":"\u8d64"
},
{
"r":0,
"b":0,
"name":"green",
"g":255,
"name_ja":"\u7dd1"
},
{
"r":0,
"b":255,
"name":"blue",
"g":0,
"name_ja":"\u9752"
}
]
}
さいごに
DynamoDBは設計(使い方)次第でいろんな事ができると実感しました。設計力を磨いていきたいですね!