DynamoDB 中的分頁
DynamoDB 絕不會在一次呼叫中傳回「所有」結果。一個 Query 或 Scan 最多傳回 1 MB 的資料,然後交給你一個 LastEvaluatedKey 以便接續。要正確分頁,意味著在那個鍵上迴圈 — 而非在計數器上。
迴圈
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,那通常是個應該改為新增索引的訊號。
試用 DynoTable,以視覺化方式翻閱查詢結果,並由它為你追蹤游標。