![見出し画像](https://assets.st-note.com/production/uploads/images/57465878/rectangle_large_type_2_ced1390af873f310a49e6e6e5ff015bd.jpg?width=1200)
AWS LambdaからDynamoDBをさわってみる
こんばんは。
本日はLambdaからDynamoDBを操作してみたいと思います。
DynamoDBはスキーマレスのNoSQLデータベースです。
通常はAppSyncを介してGraphQLを動かすためのデータベースとして使用されますが、DynamoDB自体は一般的なNoSQLデータベースです。
LambdaからDynamoDBへのアクセスは非常に簡単です。
処理の流れとしては、Lambda → AppSync → DynamoDBという順序でデータを投入することができます。
今回はDynamoDBの作成とAppSyncの設定を行い、Lambdaで処理を書いてDynamoDBにデータを投入してみたいと思います。
1.DynamoDBの設定
まずはいつものように、Serverless Frameworkを使用してDynamoDBのテーブルを作成します。
DynamoDBの設定は別途ymlファイルに記述し、resourcesセクションで読み込む形式となります。
# serverless.yml
resources:
- ${file(resources/dynamodb.yml)}
# dynamodb.yml
Resources:
sampleTable:
Type: AWS::DynamoDB::Table
Properties:
TableName: sampleTable
AttributeDefinitions:
- AttributeName: id
AttributeType: S
KeySchema:
- AttributeName: id
KeyType: HASH
ProvisionedThroughput:
ReadCapacityUnits: 1
WriteCapacityUnits: 1
同時にLambdaからDynamoDBにアクセスするためには、LambdaにDynamoDBへのアクセス権限を与える必要があります。
そのためには、ロールに適切な許可を追加します。
2.AppSyncの設定
AppSyncの設定をServerless Frameworkのymlファイルに書くためには、AppSyncのプラグインをインストールし、pluginsに追記する必要があります。
$ yarn add -D serverless-appsync-plugin
plugins:
- serverless-bundle
- serverless-offline
- serverless-dotenv-plugin
- serverless-layers
- serverless-step-functions
- serverless-appsync-plugin // 追記
custom:
// ここから追記
appSync:
name: ${self:service}-${self:provider.stage}
region: ap-northeast-1
authenticationType: API_KEY // API_KEYにする
mappingTemplatesLocation: resolvers // resolver処理の入ったディレクトリを指定
mappingTemplates: // resolver処理の中無を指定
-
type: Mutation
field: createStatus
dataSource: transactionsTable
schema: schema.graphql
dataSources: // AppSyncから触るデータソースを指定
- type: AMAZON_DYNAMODB
name: transactionsTable
config:
tableName: transactionsTable
iamRoleStatements:
- Effect: Allow
Action:
- dynamodb:*
Resource:
- arn:aws:dynamodb:${self:provider.region}:*:table/transactionsTable
- arn:aws:dynamodb:${self:provider.region}:*:table/transactionsTable/*
region: ap-northeast-1
3.AppSyncのresolverを書く
そもそも"resolver"とは、以下のようなものです。
AppSyncのリゾルバーは、GraphQLのスキーマで受け付けたリクエストに対し実際にデータ操作を行う部分で、Apache Velocity Template Language(VTL)というプログラミング言語で記述することができます。
リクエストを受けた際に、受けたデータの操作方法を決定することができるのが"resolver"です。
しかし、VTLという微妙なシンタックスの言語で書かなければならないことや、resolver自体が不要であるほうが良いという要望もあるかもしれません。それでも、我慢してresolverを書いていきましょう。
今回のケースでは、単純にPOSTするだけなので、graphqlのスキーマとMutationの定義だけを作成します。
ただし、このresolverはリクエストとレスポンスの両方が必要です。
// shcema.graphql
type Status {
id: ID!
status: String
}
input CreateStatusInput {
id: ID!
status: String
}
type Mutation {
createStatus(input: CreateStatusInput!): Status!
}
// Mutation.createStatus.request.vtl - リクエスト
{
"version": "2017-02-28",
"operation": "PutItem",
"key": {
"id": $util.dynamodb.toDynamoDBJson($ctx.args.input.id)
},
"attributeValues": $util.dynamodb.toMapValuesJson($ctx.args.input),
"condition": {
"expression": "attribute_not_exists(#id)",
"expressionNames": {
"#id": "id"
}
}
}
// Mutation.createStatus.response - レスポンス
$util.toJson($context.result)
これでDynamoDBの設定とAppSyncの設定が完了しました。
一旦deployコマンドを実行してDynamoDBのテーブルを作成しましょう。
また、AppSyncのエンドポイントとAPI-KEYも生成しておきます。
4.Lambdaに処理を書く
Lambdaのコードを書いていきましょう。
DynamoDBを操作する際には、以下のようなの2つの方法があります。
● AWS.DynamoDB.DocumentClientを使う方法
● 普通にエンドポイントにPOSTする方法
AWS.DynamoDB.DocumentClientは非常に便利で、JavaScriptのデータ型を自動的にDynamoDB上のデータ型に変換してくれます。
しかし、なぜかLambdaからAppSyncを叩くことがうまくいきませんでした。
そこで、今回はfetchライブラリを使用して直接エンドポイントにPOSTする方法を試してみたいと思います。
まずはnode-fetchをインストールしましょう。
$ yarn add -D node-fetch
では、次にDynamoDBへのPUT処理を実装していきましょう。
# index.ts
import { scanItems, getItem, putItem, deleteItem } from './services.ts';
import fetch from 'node-fetch';
//-----------------------------------
// テーブルにデータを保存する
//-----------------------------------
export const create = async (params: any) => {
const body = JSON.parse(event.body);
// PUTする内容
const variables = {
input: {
id: `evt_${body.id}`,
status: 'Do Mutation.'
}
}
// Mutationイベント
const query = `
mutation CreateStatus($input: CreateStatusInput!) {
createStatus(input: $input) {
id
status
}
}
`;
// PUTする処理
const response = await fetch('appsyncのコンソールから確認してgraphqlエンドポイントを入れる', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Accept': 'application/json',
'X-Api-Key': 'appsyncのコンソールから確認してAPI-KEYを入れる'
},
body: JSON.stringify({
query,
variables
})
});
// レスポンス
const res = await response.json();
console.log(res);
return {
statusCode: 200,
body: JSON.stringify({
message: "Mutation Done."
}),
};
}
それでは、書いたコードをデプロイしてみましょう。
Lambda関数はAPI Gatewayをトリガーとして実行されます。
クライアント側からAPIを呼び出す際には、IDをリクエストのボディに含めることで、Lambda関数の引数であるeventにJSON形式で渡されます。
渡されたevent.bodyをパースしてIDを取り出しましょう。
取得したIDを利用して、自由にDynamoDBにPUT操作を行うことができます。
これにより、クライアント側からIDを渡すことで、DynamoDBへの自由なPUT操作が可能になりました。
このコードをデプロイすることで、API Gatewayのエンドポイントが生成されます。
クライアントからエンドポイントに対してリクエストを送信し、IDをボディに含めることで、DynamoDBへのPUT操作を実行できます。
以上で、クライアント側からIDを渡してDynamoDBへの自由なPUT操作が可能となりました。
それでは。