DynamoDB UpdateItem in Node.js (AWS SDK v3)
Der Low-Level-v3-Client spricht in beide Richtungen DynamoDB-JSON — das heißt, jede Zahl, die du schickst, und jede Zahl, die du zurückbekommst, ist ein String. Das ist kein Schönheitsfehler; es ist der einzige Weg, wie eine 38-stellige DynamoDB-Zahl eine Sprache überlebt, deren einziger Zahlentyp ein Double ist. Und es ist die Stelle, an der die Bugs sitzen.
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 updateGegen ein Item, das weder Genre noch Awards hatte, kommt response.Attributes so zurück:
{"Artist":{"S":"Arturo Sandoval"},"Awards":{"N":"1"},"Genre":{"S":"Latin Jazz"},"Year":{"N":"1994"},"SongTitle":{"S":"Cubano Chant"}}typeof response.Attributes.Awards.N ist "string", also ergibt response.Attributes.Awards.N + 1 den Wert "11". Nichts wirft, nichts warnt, und die falsche Zahl landet in deinem nächsten Write. Parse an der Grenze: Number(response.Attributes.Awards.N).
Erklärung
Die Expression ist ein schlichter String, und v3 prüft ihn nicht.
UpdateItemCommandvalidiert die Form des Input-Objekts, nie die Grammatik innerhalb vonUpdateExpression— ein Tippfehler ist also ein Roundtrip und eine 400. Die Grammatik steht in Update Expressions;ADD #upd2 :updValue2ist das atomare Inkrement, undConditionExpression: 'attribute_exists(Artist)'zu ergänzen macht den Aufruf zu einem reinen Update statt zu einem Upsert.ReturnValues: 'UPDATED_NEW'ist meist das, was du willst. Dasselbe Update liefert{"Awards":{"N":"2"}}und sonst nichts.ALL_NEWschickt bei jedem Aufruf das ganze Item zurück — bei einem fetten Item ist das Bandbreite, für die du zahlst, um einen Zähler zu lesen.$metadataist v3s Out-of-Band-Kanal:{"httpStatusCode":200,"requestId":"...","attempts":1,"totalRetryDelay":0}.attemptsist die ehrliche Antwort auf „wurde das hier wiederholt?", was zählt, wenn du überlegst, ob ein nicht idempotenter Write zweimal gelaufen ist.ValidationExceptionist keine Klasse, die du fangen kannst, nur einname, den du vergleichen kannst. Ein fehlender Alias kommt alserr.name === 'ValidationException'zurück, miterr.messagegesetzt aufInvalid UpdateExpression: Attribute name is a reserved keyword; reserved keyword: Year.Der Document Client ist der andere Kompromiss.
@aws-sdk/lib-dynamodbnimmt native JS-Werte und unmarshallt die Antwort — auf Kosten genau dieser String-Sicherheit.marshall({awards: 9007199254740993})aus@aws-sdk/util-dynamodbverweigert rundheraus:Number 9007199254740992 is greater than Number.MAX_SAFE_INTEGER. Use NumberValue from @aws-sdk/lib-dynamodb.Sieh dir die Zahl in dieser Meldung genau an. Sie endet auf
2, nicht auf der3, die im Literal stand: JavaScript hatte sie bereits gerundet, bevor das SDK sie überhaupt gesehen hat. Der Low-Level-Client in diesem Snippet kann dieses Problem nicht haben, weil{N: '9007199254740993'}bis auf die Leitung Text bleibt.
Was dir eine fehlgeschlagene Bedingung liefert
Ergänze ReturnValuesOnConditionCheckFailure: 'ALL_OLD' im Input, und der geworfene Fehler trägt das Item, das dir zuvorgekommen ist:
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 ist rohes DynamoDB-JSON, egal welcher Client es geworfen hat — und es ist gratis. Ohne das ist der ehrliche Weg herauszufinden, warum ein Update mit optimistischer Nebenläufigkeit gescheitert ist, ein nachgelagertes GetItem, das einen Read kostet und schon wieder veraltet sein kann.
Der DynamoDB-JSON-Konverter macht aus diesem Payload ein einfaches JS-Objekt und zurück — der schnellste Weg, aus einem echten Item ein Fixture zu bauen. Um dieses Item überhaupt erst von einer Live-Tabelle zu holen, lade DynoTable herunter.
Verwandte Leitfäden
- DynamoDB Update Expressions —
SET,ADD,REMOVE,DELETEund Idiome. - ReturnValues verstehen — was dir jede
ReturnValues-Option liefert. - „Attribute name is a reserved keyword" — warum die Alias-Map hier nicht optional ist.
- „Invalid UpdateExpression"-Syntaxfehler — die häufigen SET-/ADD-Syntaxfehler, entschlüsselt.
Referenzen
- UpdateItem — Amazon DynamoDB API Reference
- UpdateItemCommand — AWS SDK for JavaScript v3 Reference
- Update expressions — Amazon DynamoDB Developer Guide
Zuletzt verifiziert am 2026-07-28 gegen die oben verlinkte offizielle AWS-Dokumentation.