DynamoDB 的分頁
DynamoDB 從不會在一次呼叫中回傳「全部」結果。一個 Query 或 Scan 最多回傳 1 MB 的資料,然後交給你一個 LastEvaluatedKey 讓你從那裡繼續。要把分頁做對,就是以那個鍵為條件迴圈 — 而不是以一個計數器迴圈。
DynamoDB 的分頁是怎麼運作的?
一個 Query 或 Scan 每次呼叫最多回傳 1 MB,然後交回一個 LastEvaluatedKey。要分頁,你就把那個鍵當作下一次呼叫的 ExclusiveStartKey,並迴圈直到 DynamoDB 回傳沒有鍵為止。沒有頁碼、沒有總數,而且 Limit 限制的是被評估的項目數 — 不是被回傳的項目數。
let key;
do {
const out = await client.send(new QueryCommand({...params, ExclusiveStartKey: key}));
process(out.Items);
key = out.LastEvaluatedKey;
} while (key);當 LastEvaluatedKey 是 undefined 時,你就到達了結尾。把它當作 ExclusiveStartKey 傳回去,即可取得下一片。
控制流程是一個只有在缺少鍵時才退出的單一迴圈:
每一趟不是從回傳的鍵繼續,就是停止 — 沒有計數器。
Limit 不是頁面大小
Limit 限制的是 DynamoDB 評估多少項目,而非套用 FilterExpression 之後回傳多少項目。一個帶有 filter、Limit: 25 的查詢可能只回傳 3 個項目,卻仍然交給你一個 LastEvaluatedKey — 你必須持續分頁直到鍵為空為止,即使某一頁看起來很短。一個非空的 LastEvaluatedKey 也絕不保證還有更多符合的項目;只有一個不存在的鍵才能證明你已到達結尾。
讓 SDK 替你分頁
兩個 SDK 都包裝了上面的迴圈,讓你可以直接逐頁迭代:
// AWS SDK for JavaScript v3
import {paginateQuery} from '@aws-sdk/lib-dynamodb';
for await (const page of paginateQuery({client}, params)) {
process(page.Items);
}# boto3
paginator = client.get_paginator('query')
for page in paginator.paginate(**params):
process(page['Items'])沒有頁碼
DynamoDB 沒有總數,也沒有隨機頁面存取 — 你無法跳到「第 7 頁」,也無法在不重播游標的情況下往回翻頁。請圍繞無限捲動/「載入更多」來設計 UI,而不是編號的頁面。(一個 Select: 'COUNT' 查詢為了計數,仍然會讀取 — 並計費 — 每一個符合的項目。)
給 API 用的無狀態游標
LastEvaluatedKey 只是最後一個項目的鍵屬性。把它用 Base64 編碼,當作一個不透明的 nextToken 交給用戶端;在下一次請求時再把它解碼回 ExclusiveStartKey。不需要伺服器端的游標狀態。
那個 token 是 DynamoDB-JSON — 用 DynamoDB-JSON 轉換器瞄一眼或手動打造一個。而如果你分頁是為了繞過一個 Scan,那通常是個訊號,代表你該改為新增一個索引。
想完全跳過手寫這個迴圈,查詢建構器能組合出完整的 Query/Scan 請求,並產出可執行的 SDK v3、CLI 或 boto3 程式——分頁迴圈也包含在內。
試用 DynoTable,即可視覺化地逐頁瀏覽查詢結果,並由它替你追蹤游標。