LambdaからDynamoDBに接続してみる

## 目的
AWS Certified Developer - Associateの勉強をしている中で
理解が浅いサービスについて実際に使用してみます

今回はLambdaからDynamoDBに接続してデータを取得するまでをやってみます
DynamoDBのデータ取得方法の違いについても確認します

LambdaとDynamoDBは以下で作成したものを使用します
・https://qiita.com/tsubaki_019475/items/70ab982f3ee329978383
・https://qiita.com/tsubaki_019475/items/f40c65b43103f4a9f8e4

## 手順
- ロール付与
- Lambda関数の実行
- API Gatewayを使用した接続

## ロール付与
Lambda関数の権限をデフォルトで作成した場合、DynamoDBの権限がないため設定を追加します
**1. Lambdaのページに移動、左のメニューから関数を選択**
**2. 作成したlambda関数を選択**
今回は事前に作成していたtest_lambdaを選択しています

**3. タブから設定、左のメニューからアクセス権限を選択、ロール名を選択**
ロール名を選択することでlambdaに設定してあるロールの設定ページへ移動できます

**4. 許可を追加からポリシーをアタッチ**
今回はDynamoDBからデータの取得のみ行えればよいので、`AmazonDynamoDBReadOnlyAccess`を追加しています
許可ポリシーに追加したポリシーが表示されていれば成功です

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1997750/ca19d101-9ee4-69b9-c7e3-9711444a1bc6.png)

## Lambda関数の実行
DynamoDBとlambda関数は以前作成したものを使用します

### lambda関数

関数名：test_lambda

### DynamoDB

テーブル名:test_book
パーティションキー:id

![image-3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1997750/c0d82a90-cb98-a6bc-d8ee-a8b1e97059d0.png)

テーブル名:test_book2
パーティションキー:id
ソートキー:category

![image-1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1997750/66891a05-29cc-a029-ebf2-77eba6d079e0.png)


取得方法はいくつかあります
それぞれの違いは以下のような感じです

- scan
全件取得
scanでもデータを絞ることはできるが、あくまで全件取得後に絞り込んでいる

- query
キーを条件に検索できる
条件にはパーティションキーが含まれる必要がある

- get_item
プライマリキーを条件に1つのデータを取得することができる

- batch_get_item
プライマリキーを条件に複数のデータを取得することができる


それぞれのコード例と結果は以下になります
コード実行時は作成したLambda関数のページからTestを実行しています

![image-4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1997750/b2d2f138-a8f7-7aa4-fdba-47dc1497868a.png)

### scan
https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/dynamodb/table/scan.html

コード

```
import boto3
dynamodb = boto3.resource('dynamodb')
table = dynamodb.Table("test_book2")

def lambda_handler(event, context):
    response = table.scan()
    return response['Items']

```

結果

```
[
  {
    "category": "1",
    "id": "2",
    "name": "book3"
  },
  {
    "category": "1",
    "id": "1",
    "name": "book1"
  },
  {
    "category": "2",
    "id": "1",
    "name": "book2"
  }
]
```

### query
https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/dynamodb/table/query.html

コード

```
import boto3
from boto3.dynamodb.conditions import Key
dynamodb = boto3.resource('dynamodb')
table = dynamodb.Table("test_book2")

def lambda_handler(event, context):
    response = table.query(
        KeyConditionExpression=Key('id').eq('1')
    )
    return response['Items']

```

結果
```
[
  {
    "category": "1",
    "id": "1",
    "name": "book1"
  },
  {
    "category": "2",
    "id": "1",
    "name": "book2"
  }
]
```

ソートキーであるcategoryを検索条件にするとidが検索条件にないというエラーが発生しました


コード

```
KeyConditionExpression=Key('category').eq('1')
```
結果

```
"An error occurred (ValidationException) when calling the Query operation: Query condition missed key schema element: id"
```


### get_item
https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/dynamodb/table/get_item.html

コード

```
import boto3
dynamodb = boto3.resource('dynamodb')
table = dynamodb.Table("test_book2")

def lambda_handler(event, context):
    response = table.get_item(
        Key={
            'id': '1',
            'category': '2'
        }
    )

    return response['Item']

```

結果
```
{
  "category": "2",
  "id": "1",
  "name": "book2"
}
```

Keyの指定をidのみのするとプライマリキーにならないためかエラーになりました

コード

```
        Key={
            'id': '1'
        }
```

結果

```
An error occurred (ValidationException) when calling the GetItem operation: The provided key element does not match the schema
```

### batch_get_item
https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/dynamodb/service-resource/batch_get_item.html

コード

```
import boto3
dynamodb = boto3.resource('dynamodb')

def lambda_handler(event, context):
    response = dynamodb.batch_get_item(
        RequestItems={
            'test_book2': {
                'Keys': [
                    {
                        'id': '1',
                        'category': '2'
                    },
                    {
                        'id': '2',
                        'category': '1'
                    }
                ]
            },
            'test_book': {
                'Keys': [
                    {
                        'id': '1'
                    }
                ]
            }
        }
    )

    return response['Responses']


```

結果
```
{
  "test_book2": [
    {
      "category": "2",
      "id": "1",
      "name": "book2"
    },
    {
      "category": "1",
      "id": "2",
      "name": "book3"
    }
  ],
  "test_book": [
    {
      "value": 100,
      "id": "1",
      "name": "book1"
    }
  ]
}
```

## API Gatewayを使用した接続
以前作成したAPI GatewayのURLへアクセスするとDynamoDBのデータを確認できました

![image-5.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1997750/8ead6ea3-b617-bb30-2f45-a9667c2f06d2.png)

URLを忘れた場合はAPI Gatewayの左のメニューのステージから確認できます

![image-6.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1997750/c34ed1e1-09b2-cbb6-afde-dfa63e58f181.png)