Node.js(AWS SDK v3)中的 DynamoDB Query

在 AWS SDK v3 中,一次完整的 Query 是下面那個 do/while,而不是多數程式碼片段所展示的單一 client.send():一頁上限是 1 MB,分割區的其餘部分只有在你把 LastEvaluatedKey 餵回去之後才會抵達。至於 Query 究竟是不是對的讀取方式,請見 Query vs. Scan

程式碼

import {DynamoDBClient, QueryCommand} from '@aws-sdk/client-dynamodb';

const client = new DynamoDBClient({region: 'us-east-1'});

const items = [];
let lastEvaluatedKey;

do {
  const response = await client.send(
    new QueryCommand({
      TableName: 'Music',
      KeyConditionExpression: '#hashKey = :hashKeyValue AND begins_with(#rangeKey, :rangeKeyValue)',
      ExpressionAttributeNames: {
        '#hashKey': 'Artist',
        '#rangeKey': 'SongTitle'
      },
      ExpressionAttributeValues: {
        ':hashKeyValue': {S: 'Arturo Sandoval'},
        ':rangeKeyValue': {S: 'C'}
      },
      ExclusiveStartKey: lastEvaluatedKey
    })
  );

  items.push(...(response.Items ?? []));
  lastEvaluatedKey = response.LastEvaluatedKey;
} while (lastEvaluatedKey);

console.log(`Found ${items.length} items`);

這個迴圈實際上做了什麼

對一個 600 首歌的測試資料集執行,每首歌約 3.9 KB,全部落在 Artist = "Arturo Sandoval" 之下,上面的迴圈會送出三個請求:

來回CountScannedCount讀取單位LastEvaluatedKey
1271271128.5
2271271128.5
3585827.5

沒有人設定過 271。那是 1 MB 用完的地方,所以只要你的項目大小一變,頁面邊界就跟著動。一個今天只分一頁的分割區,在你加了一個屬性之後就會分成兩頁,而從單一 send() 讀取 response.Items 的程式碼,會無聲地回傳 600 首歌中的 271 首,不報任何錯。

現在對同一個查詢加上 Limit: 10 與一個針對 YearFilterExpression

Count: 0   ScannedCount: 10   ConsumedCapacity: 5   LastEvaluatedKey: set

評估了十個項目,回傳零個,而這個請求照樣花掉讀取容量。Limit 限制的是 DynamoDB 讀取的量,而 filter 是在那之後才執行,所以一個被當成「給我 10 筆結果」來設定的 Limit,給你的會是 0 到 10 筆之間。

已於 2026-07-28 在 node v24.18.0 上,以 @aws-sdk/client-dynamodb 3.1095.0 對照 DynamoDB Local(amazon/dynamodb-local)量測。各項計數與容量皆為引擎自身的回應欄位。

說明

  • ExclusiveStartKey: lastEvaluatedKey 在第一輪是 undefined,而那是刻意的:v3 序列化器會丟掉 undefined 的成員,所以同一個物件字面值對第一個請求與之後每一次續讀都適用。若把它換成 {} — 那個「從頭開始」的直覺猜法 — 會以 ValidationException: The provided starting key is invalid 失敗。
  • @aws-sdk/client-dynamodb 從來不會替你 marshal。值以 {S: 'Arturo Sandoval'} 的形式進去,項目也以同樣的形式回來。那是不引入 DocumentClient 的代價;如果你寧可寫單純的 JS 物件,@aws-sdk/lib-dynamodb 就是該拿來用的包裝。
  • 數字是以字串形式熬過這趟來回的。用 @aws-sdk/util-dynamodbunmarshall 解出 {N: '9007199254740993'} 會得到一個 JS bigint,而不是會失真的 number;傳入 {wrapNumbers: true} 則會拿到 {value: '9007199254740993'}。無論哪一種,都不要對一個你沒檢查過大小的 DynamoDB N 直接呼叫 Number()
  • KeyConditionExpression 接受一個對 partition key 的等值條件,外加至多一個 sort key 條件(=<<=>>=BETWEENbegins_with)。其他任何條件都屬於 FilterExpression,而它是在讀取之後才執行。
  • ScanIndexForward: false 會反轉 sort key 的排序;預設是遞增。IndexName 則能把同一個指令切換到某個 secondary index。

改用視覺化操作

DynamoDB 查詢建構器會把這整個形狀 — key 條件、名稱與值對應,以及 LastEvaluatedKey 迴圈 — 產生成一支可執行的 SDK v3 程式,於是分頁就不再是你會忘掉的那一塊。

若想在 GUI 中對真正的表格執行查詢,搭配 key 條件表單與分頁結果格線,請下載 DynoTable

相關指南

參考資料

以視覺化方式建構此請求

在免費的 DynamoDB 查詢建構器中組合此操作 — 鍵條件、Filter、Index、Limit、排序方向與分頁迴圈 — 再把它複製成可執行的 SDK v3、CLI 或 boto3 程式。

開啟 DynamoDB 查詢建構器

不必透過主控台就能操作 DynamoDB

一款快速的 DynamoDB 桌面用戶端,可執行 DynamoDB 無法執行的真正 SQL — JOINs、GROUP BY、聚合 — 並支援視覺化編輯與使用你自己的 Bedrock 金鑰的 AI 代理。

30 天免費試用,無需信用卡 — 之後為無時間限制的免費方案。