AWS の DynamoDB に保存されたデータを Python から効率的に取得する方法をご紹介します。
前回は scan を使った全件検索を解説しましたが、今回は query を使った効率的なデータ取得に絞って解説します。
前回の記事をまだ見ていない方はこちらをご覧ください。
scan と query の違い
-
scan: テーブル全体を読み込みます(フルスキャン)。キー以外の属性でもフィルタできますが、テーブルサイズに比例してコストと時間がかかります。 -
query: パーティションキー(必須)とソートキー(任意)を指定して、特定のデータ群を効率的に検索します。scanに比べて非常に高速かつ低コストです。
前提条件
- AWS CLI がインストール済み
- Python3 系と boto3 がインストール済み
-
前回の記事 を参考に、AWS のプロファイル設定 (
~/.aws/config,~/.aws/credentials) が完了している
1. boto3 でセッションとテーブルを取得する
前回と同様に、boto3 でセッションを作成し、操作対象のテーブルを取得します。
import boto3
# 前回の記事で設定したプロファイル名を指定
session = boto3.Session(profile_name="my-profile")
# DynamoDB リソースを取得
dynamodb = session.resource("dynamodb")
# テーブル指定
table = dynamodb.Table("取得したいテーブル名")
2. query でデータを取得する (パーティションキーのみ)
query を使うときは、boto3.dynamodb.conditions から Key をインポートします。
query の検索条件は KeyConditionExpression で指定します。
パーティションキーのみで検索する場合、そのキーが特定の値(eq)であるアイテムを検索します。
例えば「UserID (パーティションキー) が user-001 のアイテム」を取得する場合:
from boto3.dynamodb.conditions import Key
# 'UserID' が 'user-001'
response = table.query(
KeyConditionExpression=Key("UserID").eq("user-001")
)
items = response.get("Items", [])
# 結果を出力
for item in items:
print(item)
3. query でデータを取得する (パーティションキー + ソートキー)
ソートキーもテーブルに設定されている場合、パーティションキーとソートキーの組み合わせでさらに絞り込みが可能です。
KeyConditionExpression では、パーティションキーの条件とソートキーの条件を & (AND) で組み合わせます。
例えば「UserID (パーティションキー) が user-001 で、かつ Timestamp (ソートキー) が 2025-01-01 以降のアイテム」を取得する場合:
from boto3.dynamodb.conditions import Key
# 'UserID' が 'user-001' かつ 'Timestamp' が '2025-01-01' 以降
response = table.query(
KeyConditionExpression=Key("UserID").eq("user-001") & Key("Timestamp").gte("2025-01-01")
)
items = response.get("Items", [])
# 結果を出力
for item in items:
print(item)
4. query で使えるキー条件一覧
query の KeyConditionExpression (Key オブジェクト) で使える条件は、scan の FilterExpression (Attr オブジェクト) よりも限定されています。
-
パーティションキー:
eq(等価) のみ使用可能です。 - ソートキー: 以下の比較演算子が使用可能です。
| 条件 | サンプルコード | 説明 |
|---|---|---|
eq |
Key("SortKey").eq(100) |
ソートキーが 100 |
lt |
Key("SortKey").lt(50) |
ソートキーが 50 未満 |
lte |
Key("SortKey").lte(80) |
ソートキーが 80 以下 |
gt |
Key("SortKey").gt(1000) |
ソートキーが 1000 より大きい |
gte |
Key("SortKey").gte(5000) |
ソートキーが 5000 以上 |
between |
Key("SortKey").between(10, 20) |
ソートキーが 10 から 20 の間 |
begins_with |
Key("SortKey").begins_with("prefix-") |
ソートキーが "prefix-" で始まる (文字列のみ) |
5. query と FilterExpression の併用
query でパーティションキー(+ソートキー)によってデータを絞り込んだ後、さらにキー以外の属性でフィルタをかけたい場合があります。
この場合、scan と同様に FilterExpression と Attr を併用できます。
from boto3.dynamodb.conditions import Key, Attr
# 'UserID' が 'user-001' (query)
# かつ
# 'Subject' が 'math' (filter)
response = table.query(
KeyConditionExpression=Key("UserID").eq("user-001"),
FilterExpression=Attr("Subject").eq("math")
)
items = response.get("Items", [])
注意点:
FilterExpression は query でデータを取得した後に適用されます。
そのため、読み取りキャパシティーユニット (RCU) は FilterExpression で除外される前のデータ量に基づいて消費されます。
FilterExpression で多くのデータが除外される場合、query は非効率になる可能性があります。
6. ページング処理 (全件取得)
query も scan と同様に、1回の API コールで取得できるデータサイズの上限 (1MB) があります。
KeyConditionExpression に一致するデータが 1MB を超える場合、response に LastEvaluatedKey が含まれます。
scan の時と同様に、LastEvaluatedKey を ExclusiveStartKey に指定して query を繰り返し実行することで、全件取得できます。
from boto3.dynamodb.conditions import Key
items = []
# 最初の query 実行
response = table.query(
KeyConditionExpression=Key("UserID").eq("user-001")
)
items.extend(response.get("Items", []))
# ページング処理(全件取得する場合)
while "LastEvaluatedKey" in response:
response = table.query(
KeyConditionExpression=Key("UserID").eq("user-001"),
ExclusiveStartKey=response["LastEvaluatedKey"]
)
items.extend(response.get("Items", []))
# 全件取得後の結果を出力
for item in items:
print(item)
まとめ
- DynamoDB から効率的にデータを取得するには
queryが基本。 -
queryはパーティションキー(必須)とソートキー(任意)で検索する。 - boto3 では
KeyConditionExpressionとKeyオブジェクトを使う。 -
queryで取得した結果に対し、さらにFilterExpression(Attr) でフィルタリングも可能(ただしコストに注意)。 - データが 1MB を超える場合は
LastEvaluatedKeyを使ったページング処理が必要。
次回はpythonを用いてExcel操作する方法を解説予定です!
最後までお読みいただきありがとうございました!
参考リンク