DynamoDBには全件を取得するScanという機能があります。
しかし、これには1回で取得できる件数に制限があります。
その場合は、何回かに分けてScanリクエストをDynamoDBに投げてやる必要があります。
今回はそのような状況の時に使える分割リクエストのサンプルを紹介していきます。
前提知識:LastEvaluatedKey
Scanリクエストは、全件を取得できなかったときに、LastEvaluatedKeyという値を返します。
これは、今回のScanリクエストでどこまでのデータを取得したかを表す値を示します。
言い換えると、これを使用することで次回のScanリクエストで前回の続きからデータを取得することができます。


具体的なプログラム
では、この仕組みをプログラムに落とし込むとどのようなソースコードになるのでしょうか。
今回は、pythonを例に見ていきます。
import botocore
import boto3
from boto3.dynamodb.conditions import Key, Attr
dynamodb = boto3.resource('dynamodb')
dynamoClient = boto3.client('dynamodb')
dynamoPaginator = dynamoClient.get_paginator('scan')
# メイン処理
def main()
# Scanリクエスト実行
dynamoDBName = 'yourDynamoDBName'
scanRes = scan_dynamo(dynamoDBName, None)
# 結果セットが0件の場合、終了する
if(scanRes['Count'] <= 0):
print('DynamoDBのScan結果が0件のため処理を終了します。TableName={0}'.format(dynamoDBName))
return noticeCount
# LastEvaluatedKeyの取得
lastEvaluatedKey = None
if('LastEvaluatedKey' in scanRes):
lastEvaluatedKey = scanRes['LastEvaluatedKey']
# 結果セット分だけループ
for r in scanRes['Items']:
# 行いたい処理
# LastEvaluatedKeyが存在すれば再リクエストして続きを取得する
if lastEvaluatedKey is not None:
scanRes2 = scan_dynamo(dynamoDBName, lastEvaluatedKey)
# 結果セット分だけループ
for r in scanRes2['Items']:
# 行いたい処理
# DynamoDBを全件Scan
def scan_dynamo(dynamoDBName, lastEvaluatedKey=None):
# パラメータ設定
paginationConfig={
'MaxItems': 100,
'PageSize': 100, # ページネーション設定(今回はページネーションしないので取得件数とそろえている)
}
# Scan実行
try:
# lastEvaluatedKeyあり
if(lastEvaluatedKey):
print('lastEvaluatedKeyあり。lastEvaluatedKey={0}'.format(lastEvaluatedKey))
paginator = dynamoPaginator.paginate(
TableName=dynamoDBName,
PaginationConfig=paginationConfig,
ExclusiveStartKey=lastEvaluatedKey
)
# lastEvaluatedKeyなし
else:
print('lastEvaluatedKeyなし')
paginator = dynamoPaginator.paginate(
TableName=dynamoDBName,
PaginationConfig=paginationConfig
)
except Exception as e:
print('DynamoDBのScanに失敗しました。TableName={0}, Error={1}'.format(dynamoDBName, e))
# ページを取得(今回は1ページだけなので先頭のものを取得するのみ)
for r in paginator:
return r
初回リクエストを投げて、LastEvaluatedKeyがあれば、再リクエストして続きを取得しています。
2回で全件取得できるとは限らないので、実際は2回目以降がループになるかと思います。