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 updateSu un Item che non aveva né Genre né Awards, 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à.
UpdateItemCommandvalida la forma dell'oggetto di input, mai la grammatica dentroUpdateExpression, quindi un refuso è un round trip e un 400. La grammatica è in update expressions;ADD #upd2 :updValue2è l'incremento atomico, e aggiungereConditionExpression: '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_NEWrispedisce 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.ValidationExceptionnon è una classe che puoi intercettare, solo unnameche puoi confrontare. Un alias mancante torna comeerr.name === 'ValidationException'conerr.messageimpostato aInvalid UpdateExpression: Attribute name is a reserved keyword; reserved keyword: Year.Il document client è l'altro compromesso.
@aws-sdk/lib-dynamodbprende valori JS nativi e fa l'unmarshal della risposta, al costo di quella sicurezza sulle stringhe.marshall({awards: 9007199254740993})da@aws-sdk/util-dynamodbrifiuta 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 il3scritto 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
- Update expressions DynamoDB —
SET,ADD,REMOVE,DELETEe gli idiomi. - Capire ReturnValues — cosa ti dà ciascuna opzione di
ReturnValues. - "Attribute name is a reserved keyword" — perché la mappa di alias qui non è opzionale.
- Errori di sintassi "Invalid UpdateExpression" — i comuni errori di sintassi SET/ADD, decodificati.
Riferimenti
- UpdateItem — Amazon DynamoDB API Reference
- UpdateItemCommand — AWS SDK for JavaScript v3 Reference
- Update expressions — Amazon DynamoDB Developer Guide
Ultima verifica 2026-07-28 rispetto alla documentazione ufficiale AWS collegata sopra.