🍨
【SDK for JavaScript v3】TypeScriptでDynamoDBにCRUDする【SAM】
この記事の目的
- AWS SAMを使ってAPI Gateway + Lambda + DynamoDBを作成する
- TypeScriptを使ってDynamoDBを操作するコードの書き方が分かる(with AWS SDK for JavaScript)
この記事で話さないこと
AWS SAMの環境構築(プロジェクトディレクトリはすでにあるものとする)
この記事で作成するリソース
AWS SAMでリソース定義(temlate.yamlを見る)
template.yaml
AWSTemplateFormatVersion: '2010-09-09'
Transform: AWS::Serverless-2016-10-31
Description: |
dynamo-test
Globals:
Function:
CodeUri: src/
Runtime: nodejs20.x
Timeout: 180
Architectures:
- x86_64
Environment:
Variables:
CRUDTABLE_TABLE_NAME: !Ref CRUDTable
CRUDTABLE_TABLE_ARN: !GetAtt CRUDTable.Arn
Resources:
CreateFunction:
Type: AWS::Serverless::Function
Properties:
Handler: create.lambdaHandler
Policies:
- DynamoDBWritePolicy:
TableName: !Ref CRUDTable
- DynamoDBCrudPolicy:
TableName: !Ref CRUDTable
Events:
Api:
Type: Api
Properties:
Path: /create
Method: post
Metadata:
BuildMethod: esbuild
BuildProperties:
Minify: true
Target: es2020
Sourcemap: true
EntryPoints:
- create.ts
ReadFunction:
Type: AWS::Serverless::Function
Properties:
Handler: read.lambdaHandler
Policies:
- DynamoDBReadPolicy:
TableName: !Ref CRUDTable
- DynamoDBCrudPolicy:
TableName: !Ref CRUDTable
Events:
Api:
Type: Api
Properties:
Path: /read/{id}
Method: get
RequestParameters:
- method.request.path.id
Metadata:
BuildMethod: esbuild
BuildProperties:
Minify: true
Target: es2020
Sourcemap: true
EntryPoints:
- read.ts
UpdateFunction:
Type: AWS::Serverless::Function
Properties:
Handler: update.lambdaHandler
Policies:
- DynamoDBWritePolicy:
TableName: !Ref CRUDTable
- DynamoDBCrudPolicy:
TableName: !Ref CRUDTable
Events:
Api:
Type: Api
Properties:
Path: /update/{id}
Method: post
RequestParameters:
- method.request.path.id
Metadata:
BuildMethod: esbuild
BuildProperties:
Minify: true
Target: es2020
Sourcemap: true
EntryPoints:
- update.ts
DeleteFunction:
Type: AWS::Serverless::Function
Properties:
Handler: delete.lambdaHandler
Policies:
- DynamoDBCrudPolicy:
TableName: !Ref CRUDTable
- DynamoDBCrudPolicy:
TableName: !Ref CRUDTable
Events:
Api:
Type: Api
Properties:
Path: /delete/{id}
Method: delete
RequestParameters:
- method.request.path.id
Metadata:
BuildMethod: esbuild
BuildProperties:
Minify: true
Target: es2020
Sourcemap: true
EntryPoints:
- delete.ts
CRUDTable:
Type: AWS::Serverless::SimpleTable
Properties:
TableName: CRUDTable
↓ポイントとなったことの備忘録
Globalsセクション
このセクションでは、以下のAWS SAMリソースについて全てのリソースに設定を継承します。
AWS::Serverless::Api
AWS::Serverless::Function
AWS::Serverless::HttpApi
AWS::Serverless::SimpleTable
AWS::Serverless::StateMachine
例えば各Lambda関数でランタイムやタイムアウト値など共通の設定を使用する際に各AWS::Serverless::Function
リソース内で定義を繰り返し記述せずに済みます。
パスパラメータを指定する
コード
Events:
Api:
Type: Api
Properties:
Path: /read/{id}
Method: get
RequestParameters:
- method.request.path.id
【ポイント】
- 各関数定義のAPIイベントのプロパティで
Path
に{id}
とパスパラメータを指定する - 同じくプロパティで
RequestParameters
を指定する - 参考:Api - AWS Serverless Application Model
AWS SDK for JavaScript v3の準備
AWS SDK for JavaScript v3を使います。
npm install @aws-sdk/client-dynamodb
TypeScriptでDynamoDBにCRUDするコードを書いてみる
テーブルはこんな感じ
コードの流れ
- DynamoDBClientを初期化する
(例)const client = new DynamoDBClient({});
- リクエスト内容を定義して変数に格納
(例)const xxxRequest = ...
- ↑で定義した値を引数に、リクエストクラスのインスタンスを作成
(例)const command = new GetItemCommand(commans);
-
await client.send(command);
でDynamoDB操作!
コードを書いてみる
項目の書き込み
import { DynamoDBClient, WriteRequest, BatchWriteItemCommand } from '@aws-sdk/client-dynamodb';
const client = new DynamoDBClient({ region: 'ap-northeast-1' });
const tableName = 'CRUDTable';
const writeRequests: WriteRequest[] = [
{
PutRequest: {
Item: {
id: { S: '1' }, // 実際はリクエストパラメータで受け取った値を使用
name: { S: 'John' }, // 実際はリクエストボディで受け取った値を使用
},
},
},
{
PutRequest: {
Item: {
id: { S: '2' }, // 実際はリクエストパラメータで受け取った値を使用
name: { S: 'Alice' }, // 実際はリクエストボディで受け取った値を使用
},
},
},
];
const command = new BatchWriteItemCommand({ RequestItems: { [tableName]: writeRequests } });
await client.send(command);
項目の読み取り
import { DynamoDBClient, GetItemCommandInput, GetItemCommand } from '@aws-sdk/client-dynamodb';
const client = new DynamoDBClient({ region: 'ap-northeast-1' });
const tableName = 'CRUDTable';
const getRequest: GetItemCommandInput = {
TableName: tableName,
Key: {
id: { S: 1 }, // 実際はリクエストパラメータで受け取った値を使用
},
};
const command = new GetItemCommand(getRequest);
const { Item } = await client.send(command);
項目の更新
import { DynamoDBClient, UpdateItemInput, UpdateItemCommand } from '@aws-sdk/client-dynamodb';
const client = new DynamoDBClient({ region: 'ap-northeast-1' });
const tableName = 'CRUDTable';
const updateRequests: UpdateItemInput = {
TableName: tableName,
Key: {
id: { S: 1 }, // 実際はリクエストパラメータで受け取った値を使用
},
UpdateExpression: "set #name = :name",
ExpressionAttributeNames: {
"#name": "name",
},
ExpressionAttributeValues: {
":name": {
S: "Katy", // 実際はリクエストボディで受け取った値を使用
},
},
};
const command = new UpdateItemCommand(updateRequests);
await client.send(command);
項目の削除
import { DynamoDBClient, DeleteItemInput, DeleteItemCommand } from '@aws-sdk/client-dynamodb';
const client = new DynamoDBClient({ region: 'ap-northeast-1' });
const tableName = 'CRUDTable';
const deleteRequests: DeleteItemInput = {
TableName: tableName,
Key: {
id: { S: 1 }, // 実際はリクエストパラメータで受け取った値を使用
},
};
const command = new DeleteItemCommand(deleteRequests);
await client.send(command);
改めて、コードを書く流れを振り返る
テーブル操作自体はDynamoDBClient
のsend
メソッドにCommandを引数として渡す。Commandの定義については公式APIリファレンスを参照しつつ公式ドキュメントのコード例を参考に書いていく。この流れが基本になります。
まとめ
SDKを使用したコードを書こうとすると、いつも「あれ、どう書けばいいんだっけ?ドキュメントはどこ?結局どれが正しいの?」という気持ちになります。(SDKに限った話でもない…)
SDK for JavaScript v3のAPIリファレンスは見方が分かると読みやすいと感じました。とはいえ毎回忘れているので、基本の流れと何を参照すればいいんだっけ?をまとめてみました。
情報が膨大なドキュメントは読み慣れるのも一苦労なので、これからも一度覚えた読み方を備忘録としてまとめる習慣をつけたいと思います。
GitHubで編集を提案
Discussion