DynamoDB Scan en Node.js (AWS SDK v3)
Le do/while ci-dessous n'est pas du codage défensif. Une page de Scan filtré peut revenir avec un tableau Items vide alors qu'il reste encore de la table à lire : s'arrêter à la première réponse, c'est exactement comme ça qu'un scan annonce zéro correspondance sur une table qui en contient. Query vs. Scan explique quand éviter complètement l'opération.
Code
import {DynamoDBClient, ScanCommand} from '@aws-sdk/client-dynamodb';
const client = new DynamoDBClient({region: 'us-east-1'});
const items = [];
let lastEvaluatedKey;
do {
const response = await client.send(
new ScanCommand({
TableName: 'Music',
FilterExpression: '#filter0 >= :filterValue0',
ExpressionAttributeNames: {
'#filter0': 'Year'
},
ExpressionAttributeValues: {
':filterValue0': {N: '2010'}
},
ExclusiveStartKey: lastEvaluatedKey
})
);
items.push(...(response.Items ?? []));
lastEvaluatedKey = response.LastEvaluatedKey;
} while (lastEvaluatedKey);
console.log(`Matched ${items.length} items`);Deux pages vides, 284,5 unités de lecture, 8 éléments
Le jeu d'essai fait 600 morceaux d'environ 3,9 Ko chacun, dont exactement 8 ont Year >= 2010, et ils se trient en dernier. Voici ce que la boucle ci-dessus reçoit réellement :
| Aller-retour | Items.length | ScannedCount | Unités de lecture | LastEvaluatedKey |
|---|---|---|---|---|
| 1 | 0 | 271 | 128,5 | présente |
| 2 | 0 | 271 | 128,5 | présente |
| 3 | 8 | 58 | 27,5 | absente |
Deux pages consécutives ne renvoient rien et coûtent 128,5 unités de lecture chacune. Un code qui fait if (!response.Items.length) return annonce une table vide. La référence de l'API énonce la règle sans détour : "a scan result can result in no items meeting the criteria and the Count will result in zero", et, séparément, "a FilterExpression is applied after the items have already been read; the process of filtering does not consume any additional read capacity units".
Lis cette seconde phrase comme le fait ta facture. Le filtre est gratuit, et tout ce qu'il a jeté ne l'est pas : 284,5 unités de lecture pour livrer 8 éléments, exactement la facture que tu paierais sans aucun filtre.
Mesuré le 2026-07-28 contre DynamoDB Local (amazon/dynamodb-local) avec @aws-sdk/client-dynamodb 3.1095.0 sur node v24.18.0. Les comptes et la capacité sont les champs de réponse du moteur lui-même.
Explication
ExclusiveStartKey: lastEvaluatedKeyvautundefinedau premier passage. Le sérialiseur v3 supprime les membresundefined, donc un seul littéral d'objet couvre la première requête et toutes les suivantes. Passer{}à la place échoue avecValidationException: The provided starting key is invalid.response.Items ?? []fait un vrai travail. Combine-le avec le tableau ci-dessus : le coalescement de nullité garde l'accumulateur honnête sur les pages qui n'ont rien trouvé, et lewhilemaintient la boucle en vie au-delà.#filter0n'est pas décoratif.Yearfigure sur la liste des mots réservés d'AWS, et l'utiliser sans alias renvoieValidationException: Invalid FilterExpression: Attribute name is a reserved keyword; reserved keyword: Year.Limitcompte les éléments lus, pas les éléments renvoyés. Avec ce filtre,Limit: 10donneCount: 0etScannedCount: 10. C'est un bouton de régulation pour les pics de capacité, pas un moyen de demander dix résultats.Segment/TotalSegmentsrépartissent un scan de table complet entre des workers. Ça divise le temps d'exécution, pas le coût — les mêmes 284,5 unités sont dépensées, simplement plus vite et plus concurremment.
Ce que ça coûte sur une vraie table
284,5 unités de lecture pour 8 éléments, c'est la forme du problème, et elle croît linéairement avec la table, pas avec le résultat. Avant d'expédier un scan filtré sur un chemin critique, chiffre la lecture complète de la table à ta taille d'élément et à ton trafic dans le calculateur de tarifs DynamoDB, puis compare-la à un GSI qui transforme le même modèle d'accès en Query.
Pour explorer tes tables dans une interface graphique, avec des grilles de résultats filtrées et paginées, télécharge DynoTable plutôt que de scanner à l'aveugle depuis un script.
Guides liés
- Query vs. Scan — quand (rarement) un
Scanse justifie. - Pourquoi mon Scan DynamoDB est-il lent et coûteux ? — le modèle de coût et comment l'éviter.
- DynamoDB ProvisionedThroughputExceededException — ce qu'un scan de table complet fait à la capacité d'une table provisionnée.
- DynamoDB ThrottlingException — l'autre throttle, et comment le backoff exponentiel le gère.