Node.js (AWS SDK v3) で DynamoDB から全アイテムを取得する
SDK v3 でテーブル全体を読むとは、Scan を最後までページングすることです。各レスポンスは 1 MB で頭打ちになるので、LastEvaluatedKey を ExclusiveStartKey として戻し、それが返ってこなくなるまで繰り返します(DynamoDB のカーソルの仕組み)。
以下のループはカーソルが見えるように手書きしています。実際のコードでは、SDK にすでに同梱されている paginateScan に手を伸ばすことになるでしょう。
コード
import {DynamoDBClient, ScanCommand} from '@aws-sdk/client-dynamodb';
const client = new DynamoDBClient({region: 'us-east-1'});
const items = [];
let lastEvaluatedKey;
do {
const response = await client.send(
new ScanCommand({
TableName: 'Music',
ExclusiveStartKey: lastEvaluatedKey
})
);
items.push(...(response.Items ?? []));
lastEvaluatedKey = response.LastEvaluatedKey;
} while (lastEvaluatedKey);
console.log(`Table holds ${items.length} items`);解説
paginateScanがすでにこれをやってくれます。import {paginateScan} from '@aws-sdk/client-dynamodb'としてからfor await (const page of paginateScan({client}, {TableName: 'Music'}))です。上のループが手で扱っているのと同じ 3 つのカーソルフィールド(ExclusiveStartKey、LastEvaluatedKey、Limit)から生成されているので、切り替えても挙動は変わりません。- 完了を意味するのは
LastEvaluatedKeyが無いことだけです。Itemsが 0 件でカーソルがあるレスポンスは正常であり、テーブルが空なのではありません。Items.length === 0で break するのが典型的な「行が抜ける」バグで、FilterExpressionがあると空ページは稀どころか日常茶飯事になります。 Limitは 1 回の呼び出しで評価するアイテム数であって、合計数ではありません。これはページネーターが駆動する 3 つ目のフィールドですが、これもページネーターのpageSizeも、最終的に手元に抱える配列の大きさを制限しません。- 初回の
ExclusiveStartKey: undefinedは問題ありません。シリアライザーは undefined のメンバーを落とすので、最初の反復に特別扱いは要りません。 itemsはテーブルの大きさまで膨らみます。テーブルが小さいと分かっている場合を除き、各ページをループの中で処理して手放しましょう(書き出す、ストリームに流す、集計する)。溜め込む書き方は、テーブルがひと回り育っただけでメモリ不足のクラッシュになります。- スキャンは実行のたびに、読んだバイトすべてに課金します。
ProjectionExpressionはネットワークを流れる量を減らしますが、請求額は減らしません(理由)。FilterExpressionはアイテムが読まれて課金された後に落とします(フィルター付きの Scan)。ホットパスで欲しいのは Query です。 Segment/TotalSegmentsで分割します。N 個の非同期ワーカーが、それぞれ自分の担当スライスに対して自分のカーソルを回し、すべて 1 つの共有クライアントに乗ります。Node は喜んで並行に走らせます。変わるのは実時間だけで、読み取りコストは変わりません(それが割に合うのはどんなときか)。
ビジュアルに行う
DynamoDB クエリビルダーは、このプログラム全体を、ページネーションループも含めてフォームから生成します。SDK v3 と、他 7 つのターゲットに対応しています。
DynoTable は無限スクロールのグリッドでライブのテーブルを代わりにページングし、そのグリッドの裏にある Scan を実行可能なコードとしてエクスポートします。DynoTable をダウンロード。
関連する例
- Python で全アイテムを取得する — boto3 のページネーターによる同じ全件読み取り。
- AWS CLI で全アイテムを取得する — CLI が代わりにページングします。
- Node.js での DynamoDB Scan —
FilterExpression付きのスキャン。 - 並列スキャン — Segment/TotalSegments、ワーカー数、そして手を出す価値があるのはどんなときか。
- DynamoDB の Scan はなぜ遅くて高いのか? — コストモデルと、その回避方法。
- DynamoDB ProvisionedThroughputExceededException — テーブル全体を読むのは、これを踏む典型的なやり方です。
- 「The provided starting key is invalid」 — ページネーションループで再開キーが壊れている。
参考資料
- Scan — Amazon DynamoDB API Reference
- Scanning tables in DynamoDB — Amazon DynamoDB Developer Guide
- DynamoDB read and write operations (capacity unit consumption) — Amazon DynamoDB Developer Guide
- [
paginateScan— AWS SDK for JavaScript v3 source](https://github.com/aws/aws-sdk-js-v3/blob/main/the client-dynamodb ScanPaginator module)
最終検証日 2026-07-28、上記にリンクした公式 AWS ドキュメントに照らして確認しました。