
DynamoDBテーブルからStartとEndの期間を指定して任意デバイスのデータを取得する
この記事は公開されてから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デバイス追加します。 なお、年月日時は固定とし、分秒をランダムにしています。
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機能を使って自動削除もできますね。









