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 update

Gegen 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. UpdateItemCommand validiert die Form des Input-Objekts, nie die Grammatik innerhalb von UpdateExpression — ein Tippfehler ist also ein Roundtrip und eine 400. Die Grammatik steht in Update Expressions; ADD #upd2 :updValue2 ist das atomare Inkrement, und ConditionExpression: '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_NEW schickt 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.

  • $metadata ist v3s Out-of-Band-Kanal: {"httpStatusCode":200,"requestId":"...","attempts":1,"totalRetryDelay":0}. attempts ist die ehrliche Antwort auf „wurde das hier wiederholt?", was zählt, wenn du überlegst, ob ein nicht idempotenter Write zweimal gelaufen ist.

  • ValidationException ist keine Klasse, die du fangen kannst, nur ein name, den du vergleichen kannst. Ein fehlender Alias kommt als err.name === 'ValidationException' zurück, mit err.message gesetzt auf Invalid UpdateExpression: Attribute name is a reserved keyword; reserved keyword: Year.

  • Der Document Client ist der andere Kompromiss. @aws-sdk/lib-dynamodb nimmt native JS-Werte und unmarshallt die Antwort — auf Kosten genau dieser String-Sicherheit. marshall({awards: 9007199254740993}) aus @aws-sdk/util-dynamodb verweigert 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 der 3, 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

Referenzen

Zuletzt verifiziert am 2026-07-28 gegen die oben verlinkte offizielle AWS-Dokumentation.

Mit DynamoDB ohne die Console arbeiten

Ein schneller DynamoDB-Desktop-Client, der das echte SQL ausführt, das DynamoDB nicht kann — JOINs, GROUP BY, Aggregationen — mit visueller Bearbeitung und einem KI-Agenten auf deinen eigenen Bedrock-Schlüsseln.

30 Tage kostenlos testen, keine Kreditkarte — danach der Kostenlos-Tarif ohne Zeitlimit.