DynamoDB BatchGetItem in Node.js (AWS SDK v3)

BatchGetItem recupera fino a 100 Item per chiave primaria in una sola richiesta. Nell'AWS SDK v3 la chiamata deve essere un loop, perché UnprocessedKeys arriva in una risposta riuscita invece che come errore. Cosa lo riempie, e perché 16 MB e 1 MB per partizione sono i numeri che contano, è trattato in operazioni batch in DynamoDB. Questa pagina riguarda la chiamata v3 e ciò che ti restituisce.

Codice

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`);

Spiegazione

  • L'optional chaining non è rumore difensivo. Responses e UnprocessedKeys sono entrambi opzionali nei tipi v3, quindi response.Responses?.Music ?? [] e la guardia con Object.keys() sono esattamente ciò che chiede il compilatore. In JavaScript puro sono ciò che impedisce alla prima risposta vuota di lanciare un errore.
  • Ramifica su err.name. v3 ci mette il codice di errore del servizio, e i due fallimenti che questo comando solleva davvero non sono ripetibili, quindi non devono mai finire nel loop di backoff. Oltre 100 chiavi danno ValidationException / Too many items requested for the BatchGetItem call; la stessa chiave due volte dà Provided list of item keys contains duplicates. Entrambi sono riprodotti alla lettera nella pagina Python.
  • UnprocessedKeys arriva già nella forma di RequestItems, che è l'unico motivo per cui il loop può riassegnarlo direttamente. Non è un cursore di paginazione e non significa che la chiamata sia fallita.
  • Il backoff è un'istruzione di AWS, non una gentilezza. Il riferimento dell'API ti dice di usare "an exponential backoff algorithm" perché un retry immediato atterra sulla stessa partizione sottoposta a throttling.
  • ConsistentRead e ProjectionExpression sono per tabella, si impostano dentro ogni voce di RequestItems e non al livello superiore. È facile non accorgersene quando la mappa ha una sola chiave e sembra una richiesta piatta.

Com'è fatta davvero la risposta

Esegui il blocco qui sopra su DynamoDB Local 3.3.0 con tutte e tre le canzoni presenti, aggiungi ReturnConsumedCapacity: 'TOTAL' e stampa i titoli invece del conteggio:

order:            [ 'A Mis Abuelos', 'Misty', 'Cubano Chant' ]
UnprocessedKeys:  {}
ConsumedCapacity: [ { TableName: 'Music', CapacityUnits: 1.5 } ]

La richiesta elencava Cubano Chant, A Mis Abuelos, Misty. La risposta non è in nessuna di quelle posizioni, ed è per questo che il loop accumula in un array piatto invece di indicizzare per posizione. Riassocia gli Item alle richieste tramite i loro attributi chiave, e includi quelle chiavi in qualsiasi ProjectionExpression così ti resta qualcosa su cui fare l'associazione.

Imposta ConsistentRead: true su quella stessa voce Music e le stesse tre chiavi costano 3 unità invece di 1,5. Tre Item sotto i 4 KB ciascuno vengono fatturati come tre letture GetItem separate, a mezza unità con coerenza eventuale e a un'unità intera con coerenza forte. Il calcolatore dei prezzi converte quell'aritmetica per Item in una cifra mensile prima che tu ti impegni su un pattern di lettura.

Ora elimina Misty e riesegui: due Item, un UnprocessedKeys vuoto e 1,0 unità. La chiave mancante non è stata fatturata. Quello è un artefatto di DynamoDB Local e non il contratto; il riferimento di BatchGetItem (consultato il 2026-07-28) dice che le richieste di Item inesistenti consumano la capacità di lettura minima secondo il tipo di lettura. Non dimensionare un batch di cache miss da un'esecuzione locale.

Per recuperare un insieme di chiavi e vedere cos'è tornato davvero, senza scrivere prima il loop, scarica DynoTable.

Esempi correlati

Riferimenti

Ultima verifica 2026-07-28 rispetto alla documentazione ufficiale AWS collegata sopra.

Lavora con DynamoDB senza la Console

Un client desktop veloce per DynamoDB che esegue il vero SQL che DynamoDB non può — JOINs, GROUP BY, aggregazioni — con modifica visuale e un agente AI sulle tue chiavi Bedrock.

Prova gratuita di 30 giorni, senza carta di credito — poi il piano Free senza limiti di tempo.