boto3を用いたDynamoDBの操作(2/3)
この記事は前回のboto3ライブラリを用いたDynamoDBの操作の続きです。
nissin-geppox.hatenablog.com
QueryとScan
ここでは、Batch writeを用いて複数の要素を一度に書き込みました。
また、書き込んだ要素をQueryやScanを用いて探索しました。
以降、実際のコードと出力を示します。
まず、必要なライブラリをインポートし、Batch writeでテーブルに要素を書き込みました。
入力
import json with open("data.json", "r") as f: data = json.load(f) with table.batch_writer() as batch: for d in data: batch.put_item(Item=d)
次に、用意したテーブルに対してpartition keyを用いてQueryを実行しました。
入力
from boto3.dynamodb.conditions import Key, Attr resp = table.query( KeyConditionExpression=Key('username').eq('namihei_isono') ) pprint(resp.get("Items"))
出力
[{'age': Decimal('54'), 'date': '2021-07-25T10:00:00', 'dose': Decimal('1'), 'first_name': 'Namihei', 'last_name': 'Isono', 'prefecture': 'Chiba', 'status': 'completed', 'username': 'namihei_isono'}, {'age': Decimal('54'), 'date': '2021-08-20T10:00:00', 'dose': Decimal('2'), 'first_name': 'Namihei', 'last_name': 'Isono', 'prefecture': 'Chiba', 'status': 'completed', 'username': 'namihei_isono'}]
この出力結果より、partition keyであるusernameがnamihei_isonoという値を持つ要素を探し出すことができました。
次に、"一回目のワクチンのデータ"を指定してQueryを実行しました。
入力
resp = table.query( KeyConditionExpression=Key("username").eq("namihei_isono") & Key('dose').eq(1) ) pprint(resp.get("Items"))
出力
[{'age': Decimal('54'), 'date': '2021-07-25T10:00:00', 'dose': Decimal('1'), 'first_name': 'Namihei', 'last_name': 'Isono', 'prefecture': 'Chiba', 'status': 'completed', 'username': 'namihei_isono'}]
この出力結果より、正しい要素を探し出すことができました。
次に、ageの属性を用いてQueryを実行しました。
入力
resp = table.query( IndexName="ItemsByAge", KeyConditionExpression=Key('age').eq(11), ) pprint(resp.get("Items"))
出力
[{'age': Decimal('11'), 'date': '2021-07-20T10:00:00', 'dose': Decimal('1'), 'first_name': 'Katsuo', 'last_name': 'Isono', 'prefecture': 'Gunma', 'status': 'reserved', 'username': 'katsuo_isono'}]
この出力結果より、11歳のage属性をもつ要素を探し出すことができました。
また、prefectureの属性を用いてQueryを実行しました。
入力
resp = table.query( IndexName="ItemsByPrefecture", KeyConditionExpression=Key('prefecture').eq("Tokyo"), ) pprint(resp.get("Items"))
出力
[{'age': Decimal('3'), 'date': '2021-07-20T10:00:00', 'dose': Decimal('1'), 'first_name': 'Tarao', 'last_name': 'Huguta', 'prefecture': 'Tokyo', 'status': 'reserved', 'username': 'tarao_huguta'}, {'age': Decimal('28'), 'date': '2021-07-20T10:00:00', 'dose': Decimal('1'), 'first_name': 'Huguta', 'last_name': 'Masuo', 'prefecture': 'Tokyo', 'status': 'reserved', 'username': 'masuo_huguta'}]
この出力結果より、住所が東京にある要素を2つ探し出すことができました。
次に、検索条件を指定せずにScanを実行した。
入力
resp = table.scan() items = resp.get("Items") print("Number of items:", len(items))
出力
Number of items: 8
この出力結果より、要素が8個あることが確認できました。
また、Scanは一度に1MBのデータを探索し、上限に達した時点のデータをユーザーに戻します。よって、1MBを超えるデータを探索するには以下の入力のようにLastEvakuatedKeyのような変数を設け、再帰的に探索を実行する必要があります。
入力
resp = table.scan() items = resp.get("Items") while resp.get("LastEvaluatedKey"): resp = table.scan(ExclusiveStartKey=r["LastEvaluatedKey"]) items.extend(resp["Items"]) print("Number of items", len(items))
出力
Number of items 8
出力結果は、先ほどの探索結果と同じになります。
次に、Scanを用いて条件を満たす要素の探索を行った。
入力
resp = table.scan( FilterExpression=Attr('age').lt(27) ) pprint(resp.get("Items"))
出力
[{'age': Decimal('9'), 'date': '2021-07-20T10:00:00', 'dose': Decimal('1'), 'first_name': 'Wakame', 'last_name': 'Isono', 'prefecture': 'Saitama', 'status': 'reserved', 'username': 'wakame_isono'}, {'age': Decimal('3'), 'date': '2021-07-20T10:00:00', 'dose': Decimal('1'), 'first_name': 'Tarao', 'last_name': 'Huguta', 'prefecture': 'Tokyo', 'status': 'reserved', 'username': 'tarao_huguta'}, {'age': Decimal('11'), 'date': '2021-07-20T10:00:00', 'dose': Decimal('1'), 'first_name': 'Katsuo', 'last_name': 'Isono', 'prefecture': 'Gunma', 'status': 'reserved', 'username': 'katsuo_isono'}]
この出力結果より、27歳以下の要素を探し出すことができました。
次に、dateの属性を用いて特定の日時の一覧を取得しました。
入力
resp = table.scan( FilterExpression=Attr('date').begins_with("2021-07-25"), ) pprint(resp.get("Items"))
出力
[{'age': Decimal('54'), 'date': '2021-07-25T10:00:00', 'dose': Decimal('1'), 'first_name': 'Namihei', 'last_name': 'Isono', 'prefecture': 'Chiba', 'status': 'completed', 'username': 'namihei_isono'}]
この出力結果より、日時が2021-07-25である要素を探し出すことができました。
最後に、要素の一部の属性を取り出しました。
今回はprefecture属性のみを返すようにしました。
入力
resp = table.scan( ProjectionExpression="first_name, prefecture" ) pprint(resp.get("Items"))
出力
[{'first_name': 'Wakame', 'prefecture': 'Saitama'}, {'first_name': 'Namihei', 'prefecture': 'Chiba'}, {'first_name': 'Namihei', 'prefecture': 'Chiba'}, {'first_name': 'Huguta', 'prefecture': 'Tokyo'}, {'first_name': 'Hune', 'prefecture': 'Chiba'}, {'first_name': 'Hune', 'prefecture': 'Chiba'}, {'first_name': 'Tarao', 'prefecture': 'Tokyo'}, {'first_name': 'Katsuo', 'prefecture': 'Gunma'}]
この出力結果より、要素のfast_nameとprefectureのみを取り出すことができました。