DynamoDB UpdateItem en Node.js (AWS SDK v3)
Le client v3 bas niveau parle DynamoDB JSON dans les deux sens, ce qui veut dire que chaque nombre que tu envoies et chaque nombre que tu reçois est une chaîne. Ce n'est pas une verrue ; c'est le seul moyen pour qu'un nombre DynamoDB à 38 chiffres survive à un langage dont le seul type numérique est un double. C'est aussi là que sont les bugs.
Code
import {DynamoDBClient, UpdateItemCommand} from '@aws-sdk/client-dynamodb';
const client = new DynamoDBClient({region: 'us-east-1'});
const command = new UpdateItemCommand({
TableName: 'Music',
Key: {
Artist: {S: 'Arturo Sandoval'},
SongTitle: {S: 'Cubano Chant'}
},
UpdateExpression: 'SET #upd0 = :updValue0, #upd1 = :updValue1 ADD #upd2 :updValue2',
ExpressionAttributeNames: {
'#upd0': 'Genre',
'#upd1': 'Year',
'#upd2': 'Awards'
},
ExpressionAttributeValues: {
':updValue0': {S: 'Latin Jazz'},
':updValue1': {N: '1994'},
':updValue2': {N: '1'}
},
ReturnValues: 'ALL_NEW'
});
const response = await client.send(command);
console.log(response.Attributes); // the item after the updateSur un élément qui n'avait ni Genre ni Awards, response.Attributes revient sous la forme :
{"Artist":{"S":"Arturo Sandoval"},"Awards":{"N":"1"},"Genre":{"S":"Latin Jazz"},"Year":{"N":"1994"},"SongTitle":{"S":"Cubano Chant"}}typeof response.Attributes.Awards.N vaut "string", donc response.Attributes.Awards.N + 1 s'évalue à "11". Rien ne lève, rien n'avertit, et le mauvais nombre part dans ton écriture suivante. Analyse à la frontière : Number(response.Attributes.Awards.N).
Explication
L'expression est une simple chaîne, et v3 ne la vérifiera pas.
UpdateItemCommandvalide la forme de l'objet d'entrée, jamais la grammaire à l'intérieur d'UpdateExpression: une faute de frappe, c'est un aller-retour et un 400. La grammaire est dans les expressions de mise à jour ;ADD #upd2 :updValue2est l'incrément atomique, et ajouterConditionExpression: 'attribute_exists(Artist)'rend l'appel purement modificateur plutôt qu'un upsert.ReturnValues: 'UPDATED_NEW'est généralement celui que tu veux. La même mise à jour renvoie{"Awards":{"N":"2"}}et rien d'autre.ALL_NEWrenvoie l'élément entier à chaque appel, ce qui, sur un élément volumineux, est de la bande passante que tu paies pour lire un seul compteur.$metadataest le canal hors bande de v3 :{"httpStatusCode":200,"requestId":"...","attempts":1,"totalRetryDelay":0}.attemptsest la réponse honnête à « est-ce que ça a été réessayé », ce qui compte quand tu raisonnes sur le fait qu'une écriture non idempotente ait pu s'exécuter deux fois.ValidationExceptionn'est pas une classe que tu peux attraper, seulement unnameque tu peux comparer. Un alias manquant revient sous la formeerr.name === 'ValidationException'avecerr.messagevalantInvalid UpdateExpression: Attribute name is a reserved keyword; reserved keyword: Year.Le document client est l'autre compromis.
@aws-sdk/lib-dynamodbprend des valeurs JS natives et démarshalle la réponse, au prix de cette sécurité des chaînes.marshall({awards: 9007199254740993})depuis@aws-sdk/util-dynamodbrefuse net :Number 9007199254740992 is greater than Number.MAX_SAFE_INTEGER. Use NumberValue from @aws-sdk/lib-dynamodb.Regarde bien le nombre dans ce message. Il finit par
2, pas par le3qui était écrit dans le littéral : JavaScript l'avait déjà arrondi avant même que le SDK ne le voie. Le client bas niveau de cet extrait ne peut pas avoir ce problème, parce que{N: '9007199254740993'}reste du texte jusqu'au fil.
Ce qu'une condition échouée te remet
Ajoute ReturnValuesOnConditionCheckFailure: 'ALL_OLD' à l'entrée et l'erreur levée porte l'élément qui t'a doublé :
name: ConditionalCheckFailedException | message: "The conditional request failed" | http: 400
err.Item: {"Artist":{"S":"Arturo Sandoval"},"Awards":{"N":"2"},"Year":{"N":"1994"},"SongTitle":{"S":"Cubano Chant"},"Genre":{"S":"Latin Jazz"}}err.Item est du JSON DynamoDB brut, quel que soit le client qui l'a levé, et c'est gratuit. Sans lui, la façon honnête de savoir pourquoi une mise à jour en concurrence optimiste a échoué est un GetItem de suivi qui coûte une lecture et peut déjà être périmé à son tour.
Le convertisseur JSON DynamoDB transforme cette charge en objet JS ordinaire et inversement, ce qui est le moyen le plus rapide de construire une fixture à partir d'un vrai élément. Pour récupérer cet élément sur une table en production, télécharge DynoTable.
Guides liés
- Les expressions de mise à jour DynamoDB —
SET,ADD,REMOVE,DELETE, et les idiomes. - Comprendre ReturnValues — ce que chaque option
ReturnValueste donne. - "Attribute name is a reserved keyword" — pourquoi la map d'alias ici n'est pas facultative.
- Les erreurs de syntaxe "Invalid UpdateExpression" — les fautes de syntaxe SET/ADD courantes, décodées.
Références
- UpdateItem — Amazon DynamoDB API Reference
- UpdateItemCommand — AWS SDK for JavaScript v3 Reference
- Update expressions — Amazon DynamoDB Developer Guide
Dernière vérification le 2026-07-28 par rapport à la documentation officielle AWS liée ci-dessus.