DynamoDB の値を気軽に参照する with Bash

株式会社オズビジョンのユッコ (@terra_yucco) です。
8 月になったので、ぼちぼち Qiita を再開しますが、前のように無理に連日更新とかはしない方針で行きます。

# DynamoDB の値を気軽に参照する with Bash

とある機能を本番リリースしました。
大半の結果の整合性は SQL で RDS を確認すればいいのですが、一か所だけ DynamoDB へ書き込んでいる場所があり、一括して確認するのには何か処理を作る必要があったので、以下のようなものを作成しました。

## Tips:1 複数データを確認したい

以前に自分の別エントリでも書きましたが、最近は簡単なものであれば以下のようにしてリストを取り扱うようにしています。

リストを差し替えて何度も実行したりするような場合には、以下コードの `data` 変数に全データを持つのではなく、ファイルを指定して読み込ませれば良いかと思います。

```bash
#!/bin/bash -u

data=$( cat << EOD
datum1
datum2
 :
datumN
EOD
)

while read datum
do
  # 繰り返したい処理 with ${datum}
done << EOI
${list}
EOI
```

## Tips:2 Hash Key と Range Key を定義しているテーブルを Hash Key だけで参照する
### 構造

`$ aws dynamodb describe-table --table-name user`

```json
{
    "Table": {
        "TableArn": "arn:aws:dynamodb:ap-northeast-1:xxxxxxxxxxxx:table/user",
        "AttributeDefinitions": [
            {
                "AttributeName": "uid",
                "AttributeType": "N"
            },
            {
                "AttributeName": "regdate",
                "AttributeType": "S"
            }
        ],
        "ProvisionedThroughput": {
            "NumberOfDecreasesToday": 0,
            "WriteCapacityUnits": 5,
            "LastIncreaseDateTime": 1564653110.831,
            "ReadCapacityUnits": 6,
            "LastDecreaseDateTime": 1564394555.257
        },
        "TableSizeBytes": 15141093,
        "TableName": "user",
        "TableStatus": "ACTIVE",
        "TableId": "3716aad2-26c8-4152-8401-cd4fac53fff4",
        "KeySchema": [
            {
                "KeyType": "HASH",
                "AttributeName": "uid"
            },
            {
                "KeyType": "RANGE",
                "AttributeName": "regdate"
            }
        ],
        "ItemCount": 230666,
        "CreationDateTime": 1334625921.678
    }
}
```

# 利用スクリプト

```bash:getDataFromDynamo.sh

aws dynamodb query --table-name user \
  --key-condition-expression "uid = :name" \
  --expression-attribute-values  "{\":name\":{\"N\":\"12345678\"}}"
```

#### トラブルシュート1: query で KeyCondition を指定しない

```bash
aws dynamodb query --table-name user \
  --expression-attribute-values  "{\"uid\":{\"N\":\"12345678\"}}"
```

以下のようなエラーになります。

```
An error occurred (ValidationException) when calling the Query operation: ExpressionAttributeValues can only be specified when using expressions: FilterExpression and KeyConditionExpression are null
```

Query 呼び出しの場合には `ExpressionAttributeValues` には特定の表現しか使えない、要するに `FilterExpression` か `KeyConditionExpression` を付ける必要があるようです。


#### トラブルシュート2: Hash Key のみの指定で get-item を使う

```bash
aws dynamodb get-item --table-name user --key "{\"uid\":{\"N\":\"12345678\"}}"
```

以下のようなエラーになります。

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

以下のようにして Range Key も指定すると、データが取れるようになります。

```bash
aws dynamodb get-item --table-name user --key "{\"uid\":{\"N\":\"12345678\"}, \"regdate\":{\"S\":\"1408612723\"}}" 
```

# 作成スクリプト

```bash:getDataFromDynamo.sh
#!/bin/bash -u

data=$( cat << EOS
12345678
12345679
12345680
22345678
22345679
22345680
EOS
)

date

while read uid
do
  echo -n "${uid} : "
  aws dynamodb query --table-name user \
    --key-condition-expression "uid = :name" \
    --expression-attribute-values  "{\":name\":{\"N\":\"${uid}\"}}" | jq .Items[].status[]
done << EOI
${list}
EOI

date
```

無事に状況の確認ができました。

# Conclusion

DynamoDB は SDK 経由で PHP などから取り扱うのが便利ではありますが、aws cli を利用すればコマンドラインから簡易に参照するのもそこまで大変ではありません。
ぜひ、気軽に使いこなしていただければと思います。