この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。
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デバイス追加します。 なお、年月日時は固定とし、分秒をランダムにしています。
putter.py
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機能を使って自動削除もできますね。