DynamoDB Espressioni di condizioni: la guida completa (con esempi)
Un'espressione condizionale è un predicato che DynamoDB valuta sull'elemento esistente prima che impegni la tua scrittura. Se il predicato è falso, la scrittura lo è rifiutato e non cambia nulla. È la cosa più vicina che DynamoDB abbia ad a Clausola "WHERE" su una scrittura - e l'unico modo sicuro per imporre un invariante.
Come funzionano le espressioni condizionali DynamoDB?
Un'espressione condizionale è un predicato DynamoDB valuta il lato server rispetto all'elemento corrente prima di eseguire una scrittura. Se è vero, la scrittura procede; se false, la scrittura viene rifiutata con "ConditionalCheckFailedException" e non cambia nulla. Riunisce l'assegno e la mutazione in un'unica operazione atomica, in modo che i chiamanti simultanei non possano eseguire una lettura obsoleta.
- È una guardia, non un filtro.
ConditionExpressionviene eseguito lato server sul elemento corrente; un risultato falso fallisce la scrittura con "ConditionalCheckFailedException". - Sostituisce read-then-write. Nessun viaggio di andata e ritorno
SELECTquindiUPDATE: il il controllo e la mutazione sono un'operazione atomica, quindi due chiamanti non possono gareggiare. - Il rifiuto è gratuito, non l'esecuzione gratuita. Ancora una scrittura condizionale non riuscita consuma capacità di scrittura. Una fattura di scrittura rifiutata WCUs per la dimensione del elemento esistente rispetto al quale è stato effettuato il controllo (minimo 1): creazione se assente non riuscita costa 1 WCU.
Provenendo da SQL, dovresti leggere la riga, controllarla nel codice dell'app, quindi aggiornare. Dentro DynamoDB quel divario tra lettura e scrittura è un bug di corruzione dei dati in attesa di a chiamante simultaneo. L'espressione della condizione colma il divario.
Dove si applicano
Allega ConditionExpression a PutItem, UpdateItem, DeleteItem e
ogni azione all'interno di TransactWriteItems. Non fa parte di Query o Scan
— quelli usano FilterExpression, che è una cosa diversa nel percorso di lettura.
Questa distinzione fa inciampare le persone, quindi sii preciso:
ConditionExpression | FilterExpression | |
|---|---|---|
| Percorso | Scrive (Put/Aggiorna/Elimina) | Legge (Query/Scan) |
| Effetto sul fallimento | Rifiuta l'intera scrittura | Elimina l'elemento dai risultati |
| Vede | L'elemento corrente, prescrivi | Ogni elemento candidato, post-letto |
| Costo | Impossibile scrivere ancora fatture | Gli elementi filtrati vengono comunque fatturati per la lettura |
Entrambi funzionano lato server. La differenza sta in ciò che fa "falso": una condizione interrompe a mutazione; un filtro nasconde semplicemente una riga che hai già pagato per leggere. (AWS: Espressioni condizione)
Le funzioni che utilizzerai effettivamente
La lingua della condizione è piccola. I cavalli da lavoro:
attribute_exists(path)/attribute_not_exists(path)— fa questo
esiste sull'articolo? Il classico modo di dire "crea solo se assente" / "aggiorna". solo se presente".
- Comparatori —
=,<>,<,<=,>,>=— rispetto a un valore o un altro attributo. attribute_type,begins_with,contains,size— controlli di tipo e stringa/insieme.- "TRA... E...", "IN (...)" — portata e appartenenza.
AND,OR,NOT, parentesi - per combinare quanto sopra.
"attributo_non_esiste" sul fileè il modo canonico di fare
PutItem si comporta come un inserto che non bloccherà un elemento esistente — DynamoDB
non ha un'operazione di "inserimento" separata, quindi la condizione è la semantica di inserimento.
(AWS: Riferimento per operatori e funzioni di confronto)
Un esempio pratico: proteggere un registro dagli scoperti di conto
Prendi un registro bancario. Ogni account è un elemento:
PK = "ACCT#a7f3"
SK = "BALANCE"
clearedCents = 50000
holdCents = 0Un addebito non deve mai spingere il saldo disponibile sotto lo zero, e tu non deve mai addebitare un conto che non esiste. Due regole, entrambe applicabili nel la scrittura stessa.
Nel modo sbagliato (il fucile)
GetItem ACCT#a7f3 / BALANCE → clearedCents = 50000
if (50000 >= 30000) ... ← app-side check
UpdateItem SET clearedCents = 20000
Tra GetItem e UpdateItem, un secondo addebito può leggere lo stesso
"50000", supera il proprio controllo e scrivi anche tu. Entrambi riescono; il conto va
negativo. Questa è una gara di lettura-modifica-scrittura e nessuna quantità di convalida lato app
risolve il problema: il controllo e la scrittura sono operazioni separate.
Nel modo giusto
Piega l'assegno nella scrittura. Addebito 30000 centesimi, condizionato sul conto esistente e contenendo abbastanza:
UpdateItem ACCT#a7f3 / BALANCE
SET clearedCents = clearedCents - :amt
ConditionExpression:
attribute_exists(PK) AND clearedCents >= :amtcon :amt = 30000. Se il saldo è troppo basso o l'articolo non è mai stato creato,
DynamoDB rifiuta la scrittura con
ConditionalCheckFailedException
e l'equilibrio
è intatto. L'addebito simultaneo vede il saldo originale e lo è
confrontato con esso o vede quello aggiornato: mai una lettura obsoleta su cui ha agito.
Puoi creare e copiare l'espressione esatta (nomi, valori e tutto il resto) con il file DynamoDB generatore di espressioni invece di assemblando manualmente la mappa "ExpressionAttributeValues".
Provalo qui: questo builder è preimpostato su un PutItem sorvegliato
(attribute_not_exists) in modo da poter leggere il ConditionExpression generato:
Ispezione della guardia in DynoTable
Quando una scrittura condizionale fallisce, vuoi vedere lo stato reale dell'elemento, non indovinare a questo. Apri la voce dell'account e leggi direttamente "clearedCents".

Leggi il rifiuto, non riprovare alla cieca
"ConditionalCheckFailedException" non è un errore temporaneo: si riprova lo stesso scrivere non cambia nulla. Significa che viene applicata una regola aziendale: fondi insufficienti, creazione duplicata, versione obsoleta. Emergetelo come un risultato di dominio, non come un'infrastruttura blip.
Due cose rendono gli errori di cui è possibile eseguire il debug:
ReturnValuesOnConditionCheckFailure: ALL_OLD— DynamoDB restituisce il elemento corrente accanto all'errore, in modo da poter mostrare "il saldo era 20000, tu chiesto 30000" senza una seconda lettura. (AWS: Lavorare con gli elementi)- Distinguere i due motivi dell'errore.
attribute_exists(PK) AND clearedCents >= :amtcomprime "nessun account" e "nessun fondo" in uno solo eccezione. Se i chiamanti hanno bisogno di distinguerli, dividili in due, scrivi o controlla l'articolo restituito.
Il blocco ottimistico è lo stesso trucco
Il modello del numero di versione è solo un'espressione di condizione che indossa un file diverso
cappello. Memorizza un attributo version; ogni scrittura afferma la versione che hai letto e
lo urta:
UpdateItem ACCT#a7f3 / BALANCE
SET clearedCents = :new, version = :next
ConditionExpression: version = :seenSe un altro scrittore si è mosso per primo, version = :seen è falso, la scrittura viene rifiutata,
e tu rileggi e riprovi. Ecco come DynamoDB controlla la concorrenza senza
serrature: afferma ciò che hai visto, fallisci se si muoveva. (AWS: Blocco ottimistico con
Numero versione)
L'area di staging di DynoTable esegue questo schema per te: a
la modifica simultanea emerge come un conflitto da risolvere, non come una scrittura persa.
Insidie e passaggi successivi
- Nomi che entrano in conflitto con parole riservate.
status,size,namee ~570 gli altri sono riservati. Alimentali conExpressionAttributeNames(#s = status) oppure la richiesta viene rifiutata con una ValidationException ('Il nome dell'attributo è a parola chiave riservata'). Il reserved-words-checker prende il tuo i nomi degli attributi e restituisce la mappa degli alias pronta per essere incollata. - Una condizione non può fare riferimento a un altro elemento. Vede solo l'elemento in corso
scritto. Le invarianti tra elementi necessitano di
TransactWriteItemscon una per azioneConditionExpressiono unConditionCheckcontro un elemento sentinella. - Le scritture fallite costano comunque WCUs. Una guardia che rifiuta ancora il 90% delle volte fatture per quei rifiuti. Assicurazione economica, ma non gratuita.
Per modellare le chiavi contro cui corrono queste guardie, vedere design a tabella singola e Query vs Scan. Quando sei pronto a rilasciare il condizionale scrive rispetto a dati reali, scarica DynoTable ed eseguili rispetto i tuoi tabelle


