DynamoDB BatchGetItem in Node.js (AWS SDK v3)
BatchGetItem holt bis zu 100 Items per Primary Key in einer einzigen Anfrage. Im AWS SDK v3 muss der Aufruf eine Schleife sein, denn UnprocessedKeys kommt in einer erfolgreichen Antwort zurück und nicht als Fehler. Was es füllt und warum 16 MB und 1 MB pro Partition die Zahlen sind, auf die es ankommt, behandelt Batch-Operationen in DynamoDB. Auf dieser Seite geht es um den v3-Aufruf und darum, was er zurückgibt.
Code
import {BatchGetItemCommand, DynamoDBClient} from '@aws-sdk/client-dynamodb';
const client = new DynamoDBClient({region: 'us-east-1'});
const sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
let requestItems = {
Music: {
Keys: [
{Artist: {S: 'Arturo Sandoval'}, SongTitle: {S: 'Cubano Chant'}},
{Artist: {S: 'Arturo Sandoval'}, SongTitle: {S: 'A Mis Abuelos'}},
{Artist: {S: 'Ella Fitzgerald'}, SongTitle: {S: 'Misty'}}
]
}
};
const items = [];
let attempt = 0;
do {
const response = await client.send(new BatchGetItemCommand({RequestItems: requestItems}));
items.push(...(response.Responses?.Music ?? []));
// A partial result is NOT an error: throttling, a >16 MB response, or an
// internal failure returns the leftovers in UnprocessedKeys. Retry them
// with exponential backoff.
requestItems = response.UnprocessedKeys;
if (requestItems && Object.keys(requestItems).length > 0) {
attempt += 1;
await sleep(Math.min(100 * 2 ** attempt, 5000));
}
} while (requestItems && Object.keys(requestItems).length > 0);
console.log(`Fetched ${items.length} items`);Erklärung
- Das Optional Chaining ist kein defensives Rauschen.
ResponsesundUnprocessedKeyssind in den v3-Typen beide optional, also sindresponse.Responses?.Music ?? []und derObject.keys()-Guard genau das, was der Compiler verlangt. In reinem JavaScript sind sie das, was die erste leere Antwort davon abhält, einen Fehler zu werfen. - Verzweige über
err.name. v3 legt dort den Service-Fehlercode ab, und die beiden Fehler, die dieses Command tatsächlich auslöst, sind nicht wiederholbar — sie dürfen also nie in der Backoff-Schleife landen. Mehr als 100 Keys ergibtValidationException/Too many items requested for the BatchGetItem call; derselbe Key zweimal ergibtProvided list of item keys contains duplicates. Beide sind auf der Python-Seite wortgetreu reproduziert. UnprocessedKeyskommt bereits in der Form vonRequestItems, was der einzige Grund ist, warum die Schleife es direkt wieder zuweisen kann. Es ist kein Pagination-Cursor und es bedeutet nicht, dass der Aufruf fehlgeschlagen ist.- Der Backoff ist eine Anweisung von AWS, keine Nettigkeit. Die API-Referenz sagt dir, du sollst „an exponential backoff algorithm" verwenden, weil ein sofortiger Retry auf derselben gedrosselten Partition landet.
ConsistentReadundProjectionExpressiongelten pro Tabelle und werden innerhalb des jeweiligenRequestItems-Eintrags gesetzt, nicht auf oberster Ebene. Das übersieht man leicht, wenn die Map nur einen Key hat und wie eine flache Anfrage aussieht.
Was die Antwort tatsächlich zurückliefert
Führe den Fence oben gegen DynamoDB Local 3.3.0 aus, mit allen drei Songs vorhanden, ergänze ReturnConsumedCapacity: 'TOTAL' und logge statt der Anzahl die Songtitel:
order: [ 'A Mis Abuelos', 'Misty', 'Cubano Chant' ]
UnprocessedKeys: {}
ConsumedCapacity: [ { TableName: 'Music', CapacityUnits: 1.5 } ]Die Anfrage listete Cubano Chant, A Mis Abuelos, Misty. Die Antwort steht in keiner dieser Positionen — deshalb pusht die Schleife in ein flaches Array, statt über einen Offset zu indizieren. Ordne Items ihren Anfragen über die Key-Attribute zu und nimm diese Keys in jede ProjectionExpression auf, damit du überhaupt etwas zum Zuordnen hast.
Setze ConsistentRead: true auf denselben Music-Eintrag, und dieselben drei Keys kosten 3 Einheiten statt 1,5. Drei Items unter je 4 KB werden als drei separate GetItem-Reads abgerechnet, mit einer halben Einheit bei letztendlich konsistenten und einer vollen Einheit bei stark konsistenten Reads. Der Preisrechner übersetzt diese Pro-Item-Rechnung in eine Monatszahl, bevor du dich auf ein Lesemuster festlegst.
Lösche jetzt Misty und führe es erneut aus: zwei Items, ein leeres UnprocessedKeys und 1,0 Einheiten. Der fehlende Key wurde nicht berechnet. Das ist ein Artefakt von DynamoDB Local und nicht der Vertrag; die BatchGetItem-Referenz (abgerufen am 2026-07-28) sagt, dass Anfragen nach nicht existierenden Items die minimale Lesekapazität für den jeweiligen Lesetyp verbrauchen. Dimensioniere ein Batch aus Cache-Misses nicht anhand eines lokalen Laufs.
Um einen Satz Keys zurückzuholen und anzusehen, was tatsächlich zurückkam, ohne vorher die Schleife zu schreiben, lade DynoTable herunter.
Verwandte Beispiele
- DynamoDB BatchGetItem in Python — derselbe Batch-Read mit boto3.
- DynamoDB BatchGetItem mit der AWS CLI — derselbe Batch-Read aus der Shell.
- DynamoDB GetItem in Node.js — der Einzel-Item-Read, den das hier bündelt.
- Batch-Operationen in DynamoDB — Limits, partielles Scheitern und wann sich Batching lohnt.
- „Too many items requested for the BatchGetItem call" — mehr als 100 Keys in einer Anfrage.
- „Provided list of item keys contains duplicates" — derselbe Key zweimal in einem Batch.
Referenzen
- BatchGetItem — Amazon DynamoDB API Reference
- Error handling with DynamoDB — Amazon DynamoDB Developer Guide
- DynamoDB read and write operations (capacity unit consumption) — Amazon DynamoDB Developer Guide
Zuletzt verifiziert am 2026-07-28 gegen die oben verlinkte offizielle AWS-Dokumentation.