DynamoDBテーブルからStartとEndの期間を指定して任意デバイスのデータを取得する
DynamoDBに保存しているデータから、指定した期間のデータを取得したいことがあります。
- 指定した期間において、ドアが開いた回数が知りたい
- 指定した期間のデータでグラフを表示したい
そこで本記事では、DynamoDBに溜まっている「ドアセンサーがAWSに送信したOpenイベント」があると仮定して、任意期間で取得してみました。
環境
項目 | バージョン |
---|---|
Python | 3.7 |
データの準備をする
DynamoDBテーブルを作成する
- Hashキー:ドアデバイスのID
- Rangeキー:Openした時刻(ミリ秒)
aws dynamodb create-table \ --table-name door-usage-table \ --attribute-definitions \ AttributeName=doorId,AttributeType=S \ AttributeName=timestamp,AttributeType=N \ --key-schema \ AttributeName=doorId,KeyType=HASH \ AttributeName=timestamp,KeyType=RANGE \ --billing-mode PAY_PER_REQUEST
DynamoDBテーブルにサンプルデータを格納する
次のPythonスクリプトを実行します。データ数が多いと確認しにくいため、「1デバイスあたり10回」のイベントを3デバイス追加します。 なお、年月日時は固定とし、分秒をランダムにしています。
import boto3 import random from datetime import datetime TABLE_NAME = 'door-usage-table' dynamodb = boto3.resource('dynamodb') def put(): table = dynamodb.Table(TABLE_NAME) for device_number in range(3): put_open_event_data(device_number, table) def put_open_event_data(device_number, table): with table.batch_writer() as writer: for i in range(10): timestamp = get_timestamp() writer.put_item( Item={ 'doorId': f'door-{device_number}', 'timestamp': int(timestamp.timestamp()) * 1000, 'iso8601': timestamp.isoformat() } ) def get_timestamp(): rand_minute = int(random.uniform(0, 59)) rand_second = int(random.uniform(0, 59)) return datetime(2020, 9, 10, 13, rand_minute, rand_second) if __name__ == "__main__": put()
実行するとデータが溜まります。
python putter.py
デバイスID:0のデータ
デバイスID:1のデータ
デバイスID:2のデータ
期間指定してDynamoDBテーブルからデータ取得する
データの準備ができたため、期間指定してDynamoDBテーブルからデータを取得します。 ここでは下記時刻を指定しました。
unixtime | 時刻 | |
---|---|---|
開始時刻 | 1599711000000 | 2020-09-10T13:10:00 |
終了時刻 | 1599711620000 | 2020-09-10T13:20:20 |
KeyConditionExpression
のbetween
で開始時刻と終了時刻を指定しています。
import json import boto3 from boto3.dynamodb.conditions import Key TABLE_NAME = 'door-usage-table' START_TIMESTAMP = 1599711000000 # 2020-09-10T13:10:00 END_TIMESTAMP = 1599711620000 # 2020-09-10T13:20:20 dynamodb = boto3.resource('dynamodb') def get(): table = dynamodb.Table(TABLE_NAME) for device_number in range(3): data = get_usage(f'door-{device_number}', table) print(data) def get_usage(doorId, table): option = { 'KeyConditionExpression': Key('doorId').eq(doorId) & \ Key('timestamp').between(START_TIMESTAMP, END_TIMESTAMP) } resp = table.query(**option) return resp.get('Items', []) if __name__ == "__main__": get()
スクリプトを実行する
python getter.py
実行結果
指定した範囲のデータのみを取得できました!
取得したデータ(デバイスID:0)
[ { 'iso8601': '2020-09-10T13:10:28', 'doorId': 'door-0', 'timestamp': Decimal('1599711028000') }, { 'iso8601': '2020-09-10T13:12:05', 'doorId': 'door-0', 'timestamp': Decimal('1599711125000') }, { 'iso8601': '2020-09-10T13:18:11', 'doorId': 'door-0', 'timestamp': Decimal('1599711491000') } ]
取得したデータ(デバイスID:1)
[ { 'iso8601': '2020-09-10T13:14:31', 'doorId': 'door-1', 'timestamp': Decimal('1599711271000') } ]
取得したデータ(デバイスID:2)
[] # データなし
さいごに
DynamoDBテーブルから期間を指定してデータ取得してみました。 たとえば、デバイスから来たデータを溜めておき、任意期間のデータを取得したいケースなので活用できると思います。 保存期間が決まっているのであれば、DynamoDBのTTL機能を使って自動削除もできますね。