この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。
どうも!大阪オフィスの西村祐二です。
DynamoDBで提供されている属性の型は大きく分けて スカラー型、ドキュメント型、セット型となっています。
そのため、下記画像のように日付と時刻を登録するときは文字列データ型(String型)を使用するのがほとんどだと思います。
ただ、こちらが想定するフォーマット以外でも登録することができてしまい、 登録された時刻をみて、ある処理を実行するときなど 処理が失敗してしまう可能性があります。
今回はLambdaを使って登録されている項目のフォーマットが正しいかチェックしてみたいと思います。
DynamoDBのテーブル作成
今回はCloudFormationを使ってDynamoDBのテーブルを作成します。
テンプレートファイルを作成します。 今回作成するテーブルはプライマリーキー「Date」、ソートキー「Time」とし、 属性のデータ型を文字列データの「S」として設定しています。
$ vi dynamodb.yml
dynamodb.yml
---
AWSTemplateFormatVersion: "2010-09-09"
Resources:
myDynamoDBTable:
Type: "AWS::DynamoDB::Table"
Properties:
TableName: "dynamo-test"
AttributeDefinitions:
- AttributeName: Date
AttributeType: S
- AttributeName: Time
AttributeType: S
KeySchema:
- AttributeName: Date
KeyType: HASH
- AttributeName: Time
KeyType: RANGE
ProvisionedThroughput:
ReadCapacityUnits: 1
WriteCapacityUnits: 1
下記コマンドにてテーブルを作成します。
$ aws cloudformation validate-template --template-body file://dynamodb.yml
$ aws cloudformation create-stack dynamodb-test --template-body file://dynamodb.yml
成功したら下記画像のように作成されているはずです。
Lambda関数の作成
AWS Management Consoleにログインして、AWS Lambda Dashboardを開きます。
Lambda関数一覧の画面で、[関数の作成]ボタンをクリックします。
[一から作成]ボタンをクリックします。
名前を[dynamodb-check]とし、
ロールにはDynamoDBのテーブルをスキャンするので
"dynamodb:Scan"
を付与しておいてください。
[関数の作成]ボタンをクリックします。
移動した画面で、ランタイムのドロップダウンリストからPython 3.6を選択します。 下記、プログラムをコピペし、保存ボタンをクリックします。
import boto3
import logging
from datetime import datetime
# dynamodb
DYNAMO_TABLE_NAME = 'dynamodb-test'
dynamodb = boto3.resource('dynamodb')
table = dynamodb.Table(DYNAMO_TABLE_NAME)
def format_check(data):
try:
for i in range(len(data)):
dynamo_datetime = str(data[i]['Date'])+ " " + str(data[i]['Time'])
## 日時フォーマットに変換 (ex:2017-10-19 01:01)
get_datetime = datetime.strptime(dynamo_datetime, '%Y-%m-%d %H:%M')
print(get_datetime)
print('ok')
except Exception as e:
logger.exception("{}".format(e))
return "ERROR End"
def handler(event, context):
try:
response = table.scan()
data = response['Items']
format_check(data)
except Exception as e:
logger.exception("{}".format(e))
return "ERROR End"
簡単に解説します。 ポイントは15行目です。
get_datetime = datetime.strptime(dynamo_datetime, '%Y-%m-%d %H:%M')
pythonのdatetime.strptime
はかなり便利で、
日付や時刻に対応する書式文字列から datetime オブジェクトに変換してくれます。
また、strptimeの第二引数は第一引数のフォーマットを渡すため、 これにマッチしないとエラーとなります。 ここでエラーになるということは、つまり、想定しないフォーマットで入力されていることになります。
今回の場合は Date:2017-10-19 のような日付 Time:01:01 のような時刻が 入力されている想定です。
また、入力してほしいフォーマットが
Date:2017/10/19
のような日付の場合は
第二引数を%Y/%m/%d
のように対応する形に変更すれば、OKです。
get_datetime = datetime.strptime(dynamo_datetime, '%Y/%m/%d %H:%M')
動作確認
DynamoDBにいろいろなデータをいれて、 動作を確認してみたいと思います。
正しいフォーマットでいれてみる
[項目の作成]をクリックして、 Date:2017-10-20 Time:20:20 を登録してみました。
作成したLambda関数を実行させてみると 下記ログが出力され問題なく、変換できていることがわかります。
時刻を一桁のままでいれてみる
[項目の作成]をクリックして、 Date:2017-10-20 Time:1:1 を登録してみました。
作成したLambda関数を実行させてみると 下記ログが出力され問題なく、変換できていることがわかります。
全角を入れてみる
[項目の作成]をクリックして、 Date:2017−10−20 Time:20:20 を登録してみました。
作成したLambda関数を実行させてみると 下記ログが出力され想定どおり、エラー出力ができていることがわかります。
ありえない日程をいれてみる
[項目の作成]をクリックして、 Date:2017-15-10 Time:20:20 を登録してみました。
作成したLambda関数を実行させてみると 下記ログが出力され想定どおり、エラー出力ができていることがわかります。
ありえない時刻をいれてみる
[項目の作成]をクリックして、 Date:2017-10-20 Time:25:20 を登録してみました。
作成したLambda関数を実行させてみると 下記ログが出力され想定どおり、エラー出力ができていることがわかります。
追加で、 Date:2017-10-20 Time:20:80 を登録してみました。
作成したLambda関数を実行させてみると
下記ログが出力され
今回はなぜかunconverted data
というようなエラーが出力されました。
さいごに
いかがだったでしょうか。 Lambdaをつかって DynamoDBに登録された項目が日付型であるかチェックしてみました。 あとは、Lambdaで定期的に確認しエラーが出力されれば ユーザにメールを送信すればとりあえずは良いかと思います。 もっといいやり方があれば教えてください。
誰かのためになれば幸いです。