PutItem DynamoDB in Node.js (AWS SDK v3)

PutItem scrive un Item intero e sostituisce qualsiasi Item esistente con la stessa chiave primaria (le azioni basate sugli Item spiegano in cosa differisce da UpdateItem). Il client v3 invia direttamente DynamoDB JSON, quindi Item contiene valori { S: … } / { N: … } invece di semplice JavaScript.

Codice

import {DynamoDBClient, PutItemCommand} from '@aws-sdk/client-dynamodb';

const client = new DynamoDBClient({region: 'us-east-1'});

const command = new PutItemCommand({
  TableName: 'Music',
  Item: {
    Artist: {S: 'Arturo Sandoval'},
    SongTitle: {S: 'Cubano Chant'},
    AlbumTitle: {S: 'Danzon'},
    Year: {N: '1994'},
    Awards: {N: '0'}
  },
  ConditionExpression: 'attribute_not_exists(#cond0) AND attribute_not_exists(#cond1)',
  ExpressionAttributeNames: {
    '#cond0': 'Artist',
    '#cond1': 'SongTitle'
  }
});

try {
  await client.send(command);
  console.log('Song written');
} catch (err) {
  if (err.name === 'ConditionalCheckFailedException') {
    console.log('A song with that key already exists — not overwritten');
  } else {
    throw err;
  }
}

Spiegazione

err.name è il controllo giusto, e non è l'unica cosa presente sull'errore. Catturare la condizione fallita qui sopra e stampare l'oggetto ha dato:

err.name                     ConditionalCheckFailedException
err instanceof Error         true
err.message                  The conditional request failed
err.$metadata.httpStatusCode 400

Ogni errore v3 porta $metadata con il codice di stato, l'id della richiesta e il numero di tentativi, che è ciò che vuoi in una riga di log. err.name è stabile tra i pacchetti modulari; anche instanceof ConditionalCheckFailedException funziona, ma tira dentro la classe come import di valore, quindi i bundler la mantengono.

L'errore può consegnarti l'Item che ha bloccato la scrittura. Aggiungi ReturnValuesOnConditionCheckFailure: 'ALL_OLD' al comando e err.Item arriva popolato: cinque attributi nell'esecuzione qui sopra, con Year come {"N":"1994"}. La maggior parte degli handler di sola creazione fa un GetItem dopo il fallimento per scoprire cosa c'era già. Quel round trip è evitabile. (ReturnValues: 'ALL_OLD' è il cugino del percorso di successo; ReturnValues copre il resto.)

marshall() rifiuta più input di quanto ti aspetti. Scambiare l'Item tipizzato di questa pagina con DynamoDBDocumentClient e oggetti semplici è il passo successivo tipico, e @aws-sdk/util-dynamodb è strict per impostazione predefinita. Tre eccezioni reali, alla lettera:

{Genre: undefined}   Pass options.removeUndefinedValues=true to remove undefined values from map/array/set.
{tags: new Set()}    Pass a non-empty set, or options.convertEmptyValues=true.
{n: 9007199254740993} Number 9007199254740992 is greater than Number.MAX_SAFE_INTEGER. Use NumberValue from @aws-sdk/lib-dynamodb.

La prima è quella che arriva in produzione: un campo opzionale che è undefined invece che assente solleva un'eccezione al momento del marshalling, e removeUndefinedValues: true in DynamoDBDocumentClient.from(client, {marshallOptions}) è la correzione standard.

Rileggi la terza riga. Il letterale era 9007199254740993; il messaggio cita 9007199254740992. JavaScript aveva già arrotondato il valore prima che l'SDK lo vedesse, quindi l'SDK riporta ciò che ha ricevuto. È tutta qui la ragione per cui DynamoDB trasporta N come stringa: regge 38 cifre di precisione, mentre un number JS ne regge da 15 a 17. Tutto ciò che è davvero un identificatore appartiene a S, e tutto ciò che è davvero un decimale appartiene a NumberValue o a una stringa che formatti tu.

ConditionExpression costa capacità di scrittura anche quando dice di no. AWS: "if the expression evaluates to false, DynamoDB still consumes write capacity units from the table" (recuperato il 2026-07-28). Un loop stretto di retry di sola creazione viene fatturato per tentativo. Per calibrazione, un put riuscito di un Item da ~15 KB ha riportato "CapacityUnits": 15; le scritture arrotondano per eccesso ogni 1 KB invece dei 4 KB che usano le letture.

Gli alias sono portanti. #cond0/#cond1 si risolvono in Artist/SongTitle tramite ExpressionAttributeNames. I nomi inline funzionano finché uno non collide con una parola riservata, e a quel punto l'espressione fallisce su un attributo che non hai nemmeno toccato.

Fallo visivamente

Le regole di marshalling qui sopra sono più facili da verificare vedendo entrambe le forme affiancate. Il convertitore DynamoDB JSON gratuito trasforma JSON semplice nella forma tipizzata { S: … } e viceversa, così puoi confermare cosa avrebbe prodotto marshall() prima di inviarlo.

Per scrivere e modificare Item sulle tue tabelle — un modulo per attributo, selettori di tipo, il risultato ricopiabile come codice SDK v3 — scarica DynoTable.

Guide correlate

Riferimenti

Riprodotto il 2026-07-28 su Node v24.18.0 con @aws-sdk/client-dynamodb 3.1095.0 e @aws-sdk/util-dynamodb 3.996.7, contro DynamoDB Local (amazon/dynamodb-local) sulla porta 9000. Le stringhe di errore, la forma dell'oggetto e la lettura di capacità sono output catturato, copiato alla lettera.

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.