DynamoDB UpdateItem in Node.js (AWS SDK v3)

Il client v3 di basso livello parla DynamoDB JSON in entrambe le direzioni, il che significa che ogni numero che invii e ogni numero che ricevi è una stringa. Non è un difetto; è l'unico modo in cui un numero DynamoDB da 38 cifre sopravvive a un linguaggio il cui unico tipo numerico è un double. È anche dove stanno i bug.

Codice

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

Su un Item che non aveva né GenreAwards, response.Attributes torna così:

{"Artist":{"S":"Arturo Sandoval"},"Awards":{"N":"1"},"Genre":{"S":"Latin Jazz"},"Year":{"N":"1994"},"SongTitle":{"S":"Cubano Chant"}}

typeof response.Attributes.Awards.N è "string", quindi response.Attributes.Awards.N + 1 vale "11". Nulla lancia, nulla avverte, e il numero sbagliato finisce nella tua prossima scrittura. Fai il parsing al confine: Number(response.Attributes.Awards.N).

Spiegazione

  • L'espressione è una stringa semplice, e v3 non la controllerà. UpdateItemCommand valida la forma dell'oggetto di input, mai la grammatica dentro UpdateExpression, quindi un refuso è un round trip e un 400. La grammatica è in update expressions; ADD #upd2 :updValue2 è l'incremento atomico, e aggiungere ConditionExpression: 'attribute_exists(Artist)' rende la chiamata di solo aggiornamento invece che un upsert.

  • ReturnValues: 'UPDATED_NEW' è di solito quello che vuoi. Lo stesso aggiornamento restituisce {"Awards":{"N":"2"}} e nient'altro. ALL_NEW rispedisce l'Item intero a ogni chiamata, il che su un Item grasso è banda che paghi per leggere un solo contatore.

  • $metadata è il canale fuori banda di v3: {"httpStatusCode":200,"requestId":"...","attempts":1,"totalRetryDelay":0}. attempts è la risposta onesta a "questa chiamata ha riprovato?", il che conta quando stai ragionando se una scrittura non idempotente sia stata eseguita due volte.

  • ValidationException non è una classe che puoi intercettare, solo un name che puoi confrontare. Un alias mancante torna come err.name === 'ValidationException' con err.message impostato a Invalid UpdateExpression: Attribute name is a reserved keyword; reserved keyword: Year.

  • Il document client è l'altro compromesso. @aws-sdk/lib-dynamodb prende valori JS nativi e fa l'unmarshal della risposta, al costo di quella sicurezza sulle stringhe. marshall({awards: 9007199254740993}) da @aws-sdk/util-dynamodb rifiuta senza mezzi termini:

    Number 9007199254740992 is greater than Number.MAX_SAFE_INTEGER. Use NumberValue from @aws-sdk/lib-dynamodb.

    Guarda bene il numero in quel messaggio. Finisce con 2, non con il 3 scritto nel letterale: JavaScript lo aveva già arrotondato prima che l'SDK lo vedesse. Il client di basso livello di questo snippet non può avere quel problema, perché {N: '9007199254740993'} è testo fino al filo.

Cosa ti consegna una condizione fallita

Aggiungi ReturnValuesOnConditionCheckFailure: 'ALL_OLD' all'input e l'errore lanciato porta con sé l'Item che ti ha battuto:

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 è DynamoDB JSON grezzo indipendentemente da quale client l'abbia lanciato, ed è gratis. Senza di esso, il modo onesto per scoprire perché un aggiornamento a concorrenza ottimistica è fallito è una GetItem di follow-up che costa una lettura e potrebbe essere già di nuovo stantia.

Il convertitore DynamoDB JSON trasforma quel payload in un oggetto JS semplice e viceversa, che è il modo più rapido di costruire una fixture da un Item reale. Per estrarre quell'Item da una tabella live in primo luogo, scarica DynoTable.

Guide correlate

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.