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 update

Sur 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. UpdateItemCommand valide 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 :updValue2 est l'incrément atomique, et ajouter ConditionExpression: '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_NEW renvoie 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.

  • $metadata est le canal hors bande de v3 : {"httpStatusCode":200,"requestId":"...","attempts":1,"totalRetryDelay":0}. attempts est 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.

  • ValidationException n'est pas une classe que tu peux attraper, seulement un name que tu peux comparer. Un alias manquant revient sous la forme err.name === 'ValidationException' avec err.message valant Invalid UpdateExpression: Attribute name is a reserved keyword; reserved keyword: Year.

  • Le document client est l'autre compromis. @aws-sdk/lib-dynamodb prend 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-dynamodb refuse 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 le 3 qui é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

Références

Dernière vérification le 2026-07-28 par rapport à la documentation officielle AWS liée ci-dessus.

Travaille avec DynamoDB sans la Console

Un client de bureau rapide pour DynamoDB qui exécute le vrai SQL que DynamoDB ne peut pas — JOINs, GROUP BY, agrégations — avec édition visuelle et un agent IA sur tes propres clés Bedrock.

Essai gratuit de 30 jours, sans carte bancaire — ensuite la formule Gratuit, sans limite de durée.