DynamoDB BatchGetItem en Node.js (AWS SDK v3)
BatchGetItem récupère jusqu'à 100 éléments par clé primaire en une seule requête. Dans AWS SDK v3, l'appel doit être une boucle, parce que UnprocessedKeys arrive sur une réponse réussie plutôt que sur une erreur. Ce qui le remplit, et pourquoi 16 Mo et 1 Mo par partition sont les chiffres qui comptent, est couvert dans les opérations par lot dans DynamoDB. Cette page porte sur l'appel v3 et sur ce qu'il te rend.
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`);Explication
- Le chaînage optionnel n'est pas du bruit défensif.
ResponsesetUnprocessedKeyssont tous deux optionnels dans les types v3, doncresponse.Responses?.Music ?? []et la gardeObject.keys()sont ce que le compilateur réclame. En JavaScript pur, ce sont eux qui empêchent la première réponse vide de lever une exception. - Branche sur
err.name. v3 y place le code d'erreur du service, et les deux échecs que cette commande lève réellement ne sont pas réessayables : ils ne doivent donc jamais tomber dans la boucle de backoff. Plus de 100 clés donneValidationException/Too many items requested for the BatchGetItem call; deux fois la même clé donneProvided list of item keys contains duplicates. Les deux sont reproduits mot pour mot sur la page Python. UnprocessedKeysarrive déjà à la forme deRequestItems, ce qui est la seule raison pour laquelle la boucle peut le réaffecter directement. Ce n'est pas un curseur de pagination et ça ne veut pas dire que l'appel a échoué.- Le backoff est une consigne d'AWS, pas une politesse. La référence de l'API te dit d'utiliser "an exponential backoff algorithm" parce qu'une reprise immédiate retombe sur la même partition throttlée.
ConsistentReadetProjectionExpressionse règlent par table, à l'intérieur de chaque entrée deRequestItemset non au niveau supérieur. C'est facile à manquer quand la map n'a qu'une clé et ressemble à une requête plate.
Ce que la réponse renvoie vraiment
Exécute le bloc ci-dessus contre DynamoDB Local 3.3.0 avec les trois morceaux présents, ajoute ReturnConsumedCapacity: 'TOTAL', et journalise les titres au lieu du compte :
order: [ 'A Mis Abuelos', 'Misty', 'Cubano Chant' ]
UnprocessedKeys: {}
ConsumedCapacity: [ { TableName: 'Music', CapacityUnits: 1.5 } ]La requête listait Cubano Chant, A Mis Abuelos, Misty. La réponse n'est dans aucune de ces positions, et c'est pour ça que la boucle empile dans un tableau plat au lieu d'indexer par décalage. Fais correspondre les éléments aux requêtes sur leurs attributs de clé, et inclus ces clés dans toute ProjectionExpression pour qu'il te reste de quoi les rapprocher.
Mets ConsistentRead: true sur cette même entrée Music et les trois mêmes clés coûtent 3 unités au lieu de 1,5. Trois éléments de moins de 4 Ko chacun sont facturés comme trois lectures GetItem distinctes, à une demi-unité en cohérence à terme et une unité pleine en lecture fortement cohérente. Le calculateur de tarifs traduit cette arithmétique par élément en montant mensuel avant que tu ne t'engages sur un modèle de lecture.
Supprime maintenant Misty et relance : deux éléments, un UnprocessedKeys vide, et 1,0 unité. La clé manquante n'a rien été facturée. C'est un artefact de DynamoDB Local et non le contrat ; la référence BatchGetItem (récupérée le 2026-07-28) indique que les requêtes portant sur des éléments inexistants consomment la capacité de lecture minimale correspondant au type de lecture. Ne dimensionne pas un lot de cache misses à partir d'une exécution locale.
Pour récupérer un jeu de clés et regarder ce qui est réellement revenu, sans écrire la boucle d'abord, télécharge DynoTable.
Exemples liés
- DynamoDB BatchGetItem en Python — la même lecture par lot avec boto3.
- DynamoDB BatchGetItem avec l'AWS CLI — la même lecture par lot depuis le shell.
- DynamoDB GetItem en Node.js — la lecture unitaire que ceci regroupe.
- Les opérations par lot dans DynamoDB — limites, échec partiel, et quand le lot est rentable.
- "Too many items requested for the BatchGetItem call" — plus de 100 clés dans une seule requête.
- "Provided list of item keys contains duplicates" — deux fois la même clé dans un lot.
Références
- 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
Dernière vérification le 2026-07-28 par rapport à la documentation officielle AWS liée ci-dessus.