AWS DynamoDB入門

AWSのDynamoDBを業務で扱う機会が多いので、調べた事や、実際に触ってみた事を記事にまとめました。

## DynamoDBとは
フルマネージド型で、サーバーレスの NoSQL データベースサービス

**特徴**
・データの格納と取得に特化（高度な最適化）されている
・「値」とそれを取得するための「キー」だけを格納するというシンプルな機能を持った「Key-Valueストア」
・半構造化データをドキュメントとして保存する「ドキュメントデータベース」でもある
・1桁ミリ秒単位のレイテンシーを要求するアプリケーションにも対応
・大量のデータを速く検索できる

**プライマリキー**
・パーティションキーのみ
・パーティションキーとソートキーの組み合わせ
でデータが一意になるようにする。

**セカンダリーインデックス**
DynamoDBの仕様上、パーティションキーおよびソートキーにしか検索条件をかけられず、属性を検索条件にすることはできないので、プライマリキー以外の属性で、データに効率的にアクセスできるようにインデックスを貼る。

***1. ローカルセカンダリインデックス(LSI)***
データはそのまま、パーティションキーはそのままで、ソートキーを別の属性に変更することができます。（1つのテーブルにつき、最大5個まで、テーブルの初回構築時にしか設定できない制約がある）

例）パーティションキーが**E001**で、属性2が**Middle**のデータを取得しようとしても仕様上、属性を検索条件にすることはできません。

![スクリーンショット 2024-05-05 14.59.53.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/173182/1d5f02b8-3300-cbb0-cff2-85384ebfeafd.png)

そこで、属性2をローカルセカンダリインデックスにします。

![スクリーンショット 2024-05-05 15.00.07.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/173182/8715190d-7f55-0d50-f2a3-1ad55eb09c55.png)
これで、「パーティションキーが**E001**で、ローカルセカンダリインデックスが**Middle**」であるデータを検索することができ、「**山田桜子**」のデータを取得できます。


***2. グローバルセカンダリインデックス(GSI)***
データはそのままで、パーティションキーを別の属性に変更することができる。（パーティションキーとソートキー両方も可能）
テーブル構築後に後から20個まで追加で設定できる

****データベースにおけるインデックスとは***
インデックスを貼ることによって検索効率を高める手段。

**DynamoDBへの検索可能な仕様**
・パーティションキーおよびソートキーにしか検索条件をかけられない。属性に対して検索をかけることはできない。
・パーティションキーは必ず検索条件に指定する必要がある。ソートキーのみを検索条件にすることはできない。
・パーティションキーには、完全一致条件のみ指定できます。 例えば「xxから始まる」というような部分一致条件は指定できない。
・一方、ソートキーには「xxから始まる」というような部分一致条件が指定できます。


## 実際に触ってみた

DynamoDBを単体で触るより、Lambda、API Gatewayと組み合わせて簡単なサーバーレスアプリケーションを作ってみました。

**構成：**
クライアントからHTTP API を呼び出すと、API Gateway はリクエストを Lambda 関数にルーティング。
Lambda 関数は DynamoDB と対話し、API ゲートウェイにレスポンスを返却。
それから API Gateway はクライアントにレスポンスを返す。

![スクリーンショット 2024-05-05 10.20.15.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/173182/68419446-3ec8-fc48-2ec8-2ce6dca6a456.png)


**1. Dynamo DBのセットアップ**
DynamoDBを開き、右にあるオレンジ色の「テーブルの作成」ボタンをクリック
![スクリーンショット 2024-05-06 12.03.08.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/173182/5d67293f-9aa8-d574-9b59-70705165a747.png)

テーブル名、パーティションキー、ソートキーを設定
![スクリーンショット 2024-05-06 12.06.22.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/173182/f5798501-2b58-64fd-42c3-c93bfc3c91fc.png)

コンソール上でレコードの追加、編集、複製、削除も可能です。

**2. IAMロールのセットアップ**
IAMロールとは、AWSのリソースに対して権限を割り当てるための仕組みです。
LambdaがDynamoDBにアクセスできるようにロールを設定します。

IAMを開き、右にあるオレンジ色の「ロールを作成」ボタンをクリック
![スクリーンショット 2024-05-06 12.10.16.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/173182/8cbb5cdb-493b-b94c-d1ca-65d97201328a.png)

Lambdaに対するロールを作成するため、サービスまたはユースケースから**Lambda**を選択し「次へ」をクリックします。
![スクリーンショット 2024-05-06 12.12.25.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/173182/b098169c-1af2-9263-750a-2466858ae3c5.png)

Lambdaロールに付与する権限を選択します。DynamoDBへのアクセス権限をもつ `AmazonDynamoDBFullAccess` をポリシーとしてアタッチします。
![スクリーンショット 2024-05-06 12.15.19.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/173182/faf3e6c5-7848-6b33-85aa-a5d3bb2f8e23.png)

「次へ」をクリックし、進んだページで「ロール名」を入力し、「ロールを作成」をクリックすれば完了です。

**3. Lambdaのセットアップ**
Lambdaとは：
サーバーのプロビジョニングや管理なしでコードを実行できるサーバレスのFunction as a Service。課金は実際に使用したコンピューティング時間に対してのみ発生し、コードが実行されていないときには料金も発生しません。つまりは、プログラムの実行環境を提供してくれるので、コードだけを用意すればいいという話です。

DynamoDBはLambdaとの相性の良いデータストアであり、サーバーレスでアプリケーションを開発する際にLambdaと合わせて利用されることが多いらしいです。

今回作る Lambda 関数は、DynamoDBと連携し、項目を作成、読み取り、更新、および削除します。

Lambdaを開き、右にあるオレンジ色の「関数の作成」ボタンをクリック
![スクリーンショット 2024-05-06 13.12.27.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/173182/c773e849-bd7f-3b1d-1ef8-132318ed7dad.png)

関数名を入力し、実行ロールの変更で、既存のロールを使用するを選択すると、セレクトBOXが出てきて、そこから**2で作成したIAMロール**を選択します。これにより、このLambda関数はDynamoDBへアクセスする権限が付与されます。

ランタイムは、Java, Node.js, Python, RUbyが選べるのでお好きな環境を選択してください。
![スクリーンショット 2024-05-06 13.14.26.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/173182/bdd4d353-491b-4b05-75f9-bee3a201d53e.png)

次のページへ進むと、コードを編集するUIが出てきます。

Lambda関数にコードを登録する方法は以下の2つあります
・コンソールでコードを直接編集
・ローカルで開発したコードをアップロード（外部ライブラリなどを含む場合）

今回はシンプルな実装なので、コンソールで編集します。使用するソースコードは[こちらのサンプル](https://github.com/hitchon1/AWS_RestLambdaAPI/blob/main/lambda_function.py)から拝借させて頂きました。

![スクリーンショット 2024-05-06 13.15.19.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/173182/fd67bada-9830-db12-fffc-76c128b5d5d3.png)

「Deploy」ボタンがアクティブになるので、クリックして反映させます。

**4. API Gatewayのセットアップ**
API Gatewayとは：
あらゆる規模の REST、HTTP、および WebSocket API を作成、公開、維持、モニタリング、およびセキュア化するためのサービス

今回のケースでは、Lambdaで作った関数をAPI GatewayでAPI化するイメージです。

API Gatewayを開き、右にあるオレンジ色の「APIを作成」をクリック
![スクリーンショット 2024-05-06 14.21.12.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/173182/612aea2e-2522-344a-46c1-3a7828974634.png)

今回作るのはREST APIなので、REST APIの「構築」をクリック
![スクリーンショット 2024-05-06 14.21.45.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/173182/ff8109da-b8a2-882e-490f-b38603e80299.png)

API名を入力し、説明はブランクでもOK、エンドポイントタイプはリージョンのままで「APIを作成」をクリック
![スクリーンショット 2024-05-06 14.23.43.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/173182/a736c37b-3b34-7b3f-f538-3dc64d37e4f9.png)

リソースページに遷移するので、ここでリソースとメソッドの設定をしていきます。
![スクリーンショット 2024-05-06 14.26.32.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/173182/86acef41-9baa-9d08-83ee-ee16098f8c98.png)

まずはGETのリソースを設定します。「リソースの作成」をクリックし、リソース名を入力。
![スクリーンショット 2024-05-06 15.27.02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/173182/e3f3b68b-df5d-c358-ae0f-120e451068ab.png)

作ったリソースに対して、メソッドを作成します。「メソッドを作成」をクリック。
統合タイプは当然Lambda関数で、Lambda関数で、3で作った関数名が表示されるので、選択します。
![スクリーンショット 2024-05-06 15.33.28.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/173182/d3a66642-333b-a15c-4039-1f8e6580f5b0.png)

POST, PUT, DELETEも同様の手順で設定していき、すべて完了したら、「APIをデプロイ」をクリック。
ステージを選択するモーダルが開くので、新しいステージで、任意のステージ名を入力して、「デプロイ」をクリック
![スクリーンショット 2024-05-06 15.35.30.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/173182/9b83a7cf-0c26-35c4-85c0-d7397d475eaa.png)

デプロイするとエンドポイントのURLが発行されます。
![スクリーンショット 2024-05-06 15.35.49.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/173182/af57bb0f-f9cc-1693-9d87-59ba8657dcf6.png)

**5. APIを叩いてみる**
私はAPIテストツールの[Postman](https://web.postman.co/)を使って、4で発行されたエンドポイントに対して、まずはPOSTを実行してDynamoDBのレコードに反映されるか確認しました。その後、GET、DELETEなど各種メソッドも確認しました。

*AWSコンソール上で、API Gateway、Lambdaもテストを実行できますが、今回は省略しました。

### 参考サイト
[AWS公式](https://docs.aws.amazon.com/ja_jp/apigateway/latest/developerguide/http-api-dynamo-db.html#http-api-dynamo-db-create-function
)

## まとめ
AWSの基本、主要サービスの概要など、頭ではわかっていましたが、実際に触って、ロールのアタッチや、複数のサービスを連携させるなど、手を動かして作ってみると理解がグッと深まりました。

次はクライアントサイドと接続させ、インデックスを貼るなどしてもっと使い込んでみたいと思います。