ACCESS Advent Calendar 2022 の6日目になります。
この記事は、幅広いAWSサービスを活用できるプラットフォームのAWS Amplifyで、LambdaをExpressで構築できるAWS Serverless Express
を使用して、DynamoDBと接続、その上でCRUD処理を行う書き方についてとなります。
参考となった記事は「Create a REST API integrated with Amazon DynamoDB using AWS Amplify and Vue」となります。ほぼその記事通りの実装となります。
環境構築
LambdaでCRUD処理を書く前に環境を構築します。
各packageとAmplifyのversion
"aws-sdk": "2.1253.0",
"aws-serverless-express": "3.4.0",
"express": "4.18.2"
"Amplify CLI": "10.5.1"
ポリシー設定
CRUD処理を行う前提として、LambdaからDynamoDBにアクセスするための権限が必要となります。
そこでポリシーを設定します。
$ amplify add api
を実行した後、amplify/backend/function/{functionName}
に custom-policies.json
が自動で作成されます。
そのファイルに記述することで、Lambda関数でDynamoDBにデータが反映されます。
[
{
"Action": [
"dynamodb:PutItem", // POST
"dynamodb:Scan", // GET ALL
"dynamodb:GetItem", // GET ONE
"dynamodb:UpdateItem", // UPDATE
"dynamodb:DeleteItem" // DELETE
],
"Resource": ["arn:aws:dynamodb:*:*:table/{tableName}"],
"Effect": "Allow"
}
]
AWS Serverless Expressを使用
LambdaをExpressで構築することができます。
それは $ amplify add api
で、設定についての質問の
Choose the function template that you want to use
で、Serverless ExpressJS function (Integration with API Gateway)
を選択するとExpressで構築されたfunctionのSampleファイルが自動で作成されるので、それを見本に構築します。
DynamoDBに接続
次にDynamoDBをAmplifyで使用するには storage
を追加した上で、さらにfunction
をupdateします。
$ amplify add storage
$ amplify update function
その上でLamda関数を定義するファイルで DocumentClient
を読み込むと、DynamoDBと接続されます。
import AWS from 'aws-sdk';
const dynamodb = new AWS.DynamoDB.DocumentClient();
その DocumentClient
を読み込んだ変数 dynamodb
に各CRUD処理のメソッドを定義します。
例えばPOSTの場合は
dynamodb.put(params, (error, result) => {
if (error) {
// errorのresponseを書く
} else {
// 正常のresponseを書く
}
});
となります。
その他のCRUD処理のメソッドは下記になります。
dynamodb.scan // GET ALL
dynamodb.get // GET ONE
dynamodb.update // UPDATE
dynamodb.delete // DELETE
環境構築のおおよその設定をイメージできたのではないでしょうか。
次にCRUD処理の書き方について説明します。
CRUD処理の書き方
paramsについて
前述の POST例
でput関数の引数に params
を設定しました。
その params
は、公式ドキュメント「Calling DynamoDB from Lambda in Node.js」に記載されてるとおり、いくつかの key
とvalue
を指定することができます。
const params = {
TableName : 'your-table-name',
IndexName: 'some-index',
KeyConditionExpression: '#name = :value',
ExpressionAttributeValues: { ':value': 'shoes' },
ExpressionAttributeNames: { '#name': 'name' }
Item: {
id: '12345',
price: 100.00
}
Key: {
id: '12345'
}
ReturnValues: NONE | ALL_OLD | UPDATED_OLD | ALL_NEW | UPDATED_NEW
}
Item
はDynamoDBに登録するデータになります。
さらに Key
は既に登録済みのデータを抽出する際に指定します。とても直感的で分かりやすいですね。
例えばDynamoDBに1件新規で登録する場合は
const postUser = (request, response) => {
const timestamp = new Date().toISOString();
const params = {
TableName: tableName,
Item: {
...request.body,
id: uuidv4(),
createdAt: timestamp,
updatedAt: timestamp,
},
};
dynamodb.put(params, (error, result) => {
if (error) {
// errorのresponseを書く
} else {
// 正常のresponseを書く
}
});
};
となります。
次にDynamoDBに登録されているデータを1件抽出する場合は
const getOneUser = (request, response) => {
const params = {
TableName: tableName,
Key: {
id: request.params.userId,
},
};
dynamodb.get(params, (error, result) => {
if (error) {
// errorのresponseを書く
} else {
// 正常のresponseを書く
}
});
};
となります。
さらにDynamoDBに登録されているデータを1件削除する場合は
const deleteUser = async (request, responss) => {
const params = {
TableName: tableName,
Key: {
id: request.params.userId,
},
};
dynamodb.delete(params, (error, result) => {
if (error) {
// errorのresponseを書く
} else {
// 正常のresponseを書く
}
});
};
となります。
UPDATE処理
UPDATE処理は前述の処理と比較すると少し複雑です。
UPDATE処理には前述した params
で
UpdateExpression
ExpressionAttributeValues
-
ExpressionAttributeNames
を使用します。
その中のUpdateExpression
について、公式サイト「Update expressions」で確認すると
SET — modifying or adding item attributes
REMOVE — deleting attributes from an item
ADD — updating numbers and sets
DELETE — removing elements from a set
を指定することができます。
そこで SET
を利用して
UpdateExpression: 'SET #attributeName = :attributeValue'
と設定します。
この書き方については、「DynamoDBでデータを更新する際に使うUpdateExpressionについて一通りまとめてみた」の記事に記載されいてるとおり、
UpdateExpressionの中では #xxxなど#で始まる変数でAttributeNameを表現できる。 また、:xxxなど:で始める変数で値を表現ができる。
となります。
つまり、paramsでExpressionAttributeValues
、ExpressionAttributeNames
の ExpressionAttributeNames
はDynamoDBに登録する項目の属性名、ExpressionAttributeValues
はその属性名に登録する値になります。
UpdateExpression: 'SET #attributeName = :attributeValue'
ExpressionAttributeNames: {
'#attributeName': {属性名},
},
ExpressionAttributeValues: {
':attributeValue': {値},
}
と指定します。
具体的に例を書くと
const updateUser = (request, response) => {
const timestamp = new Date().toISOString();
const params = {
TableName: tableName,
Key: {
id: request.params.userId,
},
UpdateExpression: 'SET #title = :title, #updatedAt = :updatedAt',
ExpressionAttributeNames: {
'#title': 'title',
'#updatedAt': 'updatedAt',
},
ExpressionAttributeValues: {
':title': request.body.title,
':updatedAt': timestamp,
},
};
dynamodb.update(params, (error, result) => {
if (error) {
// errorのresponseを書く
} else {
// 正常のresponseを書く
}
}
};
になります。
こう書くことで、DynamoDBに既に登録されているid request.params.userId
に対して title
と updateAt
の値のみ変更になります。
以上となります。
いかがでしたでしょうか。
AmplifyでCRUD処理を行う際の簡単な説明とSampleコードについて書きました。
そこまで行き着くまでに、AmplifyやAWSのドキュメント、さらには参考記事を読み解く必要があるので、この記事で1つにまとめました。
一助となれば幸いです。