Key condition expression in DynamoDB
Una key condition expression è la KeyConditionExpression che passi a una
Query — l'unica parte della richiesta che DynamoDB usa per trovare gli item.
Tutto il resto (filtri, proiezioni) viene eseguito dopo che la lettura è già stata
contabilizzata.
Cos'è una key condition expression in DynamoDB?
Una key condition expression è la KeyConditionExpression di una Query che indica a DynamoDB quali item leggere. La deve essere un'uguaglianza (PK = :v); la accetta un operatore di intervallo — =, <, <=, >, >=, BETWEEN o begins_with. Determina cosa viene letto e fatturato, a differenza di un filtro.
- La partition key deve essere un'uguaglianza.
PK = :ve nient'altro — niente intervalli, nientebegins_with, nienteIN. DynamoDB ne calcola l'hash per individuare una partizione. - La sort key prende un operatore di intervallo.
=,<,<=,>,>=,BETWEEN, obegins_with— è qui che affetti una item collection. - Non è un filtro. Una key condition decide cosa viene letto e fatturato; una
FilterExpressiontaglia solo il risultato dopo che hai pagato la lettura. - Le sort key sono ordinate per byte. Gli operatori di intervallo confrontano lessicograficamente, quindi come formatti la stringa della sort key è il tuo potere di query.
Perché la partition key è bloccata sull'uguaglianza
DynamoDB memorizza gli item calcolando l'hash della partition key verso una partizione fisica. Un hash ti dà una posizione, non un intervallo — quindi non c'è nulla da scansionare attraverso.
Ecco perché PK > :v o begins_with(PK, :v) sono rifiutati categoricamente. Il
motore non può rispondere a "tutte le partizioni la cui chiave inizia per X" senza
leggere l'intera tabella, che è esattamente lo Scan che è costruito per evitare.
Venendo da SQL, questo sembra al contrario: WHERE id LIKE 'order%' è banale in
Postgres. In DynamoDB la partition key è un indirizzo, non una colonna cercabile.
La sort key è dove vive il potere
All'interno di una partizione, gli item sono memorizzati ordinati per sort key. Quell'ordinamento è ciò che gli operatori di intervallo sfruttano — DynamoDB cerca una posizione e legge in avanti.
| Operatore | Legge | Usalo per |
|---|---|---|
SK = :v | Un item esatto | Un figlio specifico tramite la sua chiave |
SK < / <= / > / >= :v | Una fetta aperta da un lato | "Tutto dopo questo punto" |
SK BETWEEN :a AND :b | Un intervallo chiuso (inclusivo) | Una finestra limitata — un intervallo di date |
begins_with(SK, :p) | Una fetta per prefisso | Un tipo o una gerarchia sotto la PK |
Non c'è LIKE, né CONTAINS, né ENDS_WITH sulla chiave. Il confronto di
sottostringa e suffisso non è ordinato per byte, quindi forzerebbe una lettura
completa — per design, l'API non te lo permette. Quelli vivono in
FilterExpression, dove hai già pagato.
(AWS: Key condition expressions)
Un esempio pratico: messaggi in un'app di chat
Diciamo che stai costruendo una chat basata su canali. Una tabella, partizionata per canale, ordinata per ora del messaggio. Key schema originale:
- Partition key
ChannelRef—CH#{channelId} - Sort key
PostedAt— un timestamp ISO-8601,MSG#2026-06-23T14:05:00Z
Il prefisso MSG# mantiene le righe dei messaggi ordinabili e distinte da
qualsiasi altro tipo di riga tu possa co-locare sotto lo stesso canale (config
fissata, membership).
Carica i messaggi più recenti di un canale. Solo la partition key, dal più recente:
KeyConditionExpression: ChannelRef = :ch
ExpressionAttributeValues: { ":ch": "CH#general" }
ScanIndexForward: falseScanIndexForward: false percorre la collection ordinata al contrario — il modo
economico per ottenere "i più recenti per primi" senza ordinare lato client.
Un giorno specifico con begins_with. Poiché il timestamp è la sort key ed è
memorizzato come testo, un prefisso di data è una fetta pulita:
KeyConditionExpression ChannelRef = :ch AND begins_with(PostedAt, :day)
:ch "CH#general"
:day "MSG#2026-06-23"
Questo legge ogni messaggio del 2026-06-23 e nient'altro — DynamoDB cerca il prefisso e si ferma quando esce dalla fine. Funziona solo perché il prefisso è un vero left-anchor di una stringa ordinata per byte.
Una finestra precisa con BETWEEN. Per "i messaggi durante l'ora delle
14:00", un intervallo inclusivo batte un prefisso:
KeyConditionExpression ChannelRef = :ch AND PostedAt BETWEEN :lo AND :hi
:ch "CH#general"
:lo "MSG#2026-06-23T14:00:00Z"
:hi "MSG#2026-06-23T14:59:59Z"
BETWEEN è inclusivo su entrambi i limiti, quindi scegli i tuoi estremi
deliberatamente — un off-by-one qui scarta o raddoppia silenziosamente un
messaggio di bordo.
Puoi assemblare e copiare una qualsiasi di queste espressioni, con la mappa
ExpressionAttributeValues riempita per te, nel
DynamoDB expression builder — comodo per
azzeccare al primo colpo la sintassi di begins_with e BETWEEN.
Vedila in DynoTable
Esegui la stessa key condition contro una partizione di canale reale e guarda la capacità consumata aggiornarsi dal vivo, così puoi confermare di star leggendo una fetta — non l'intera collection.
La trappola: confondere una key condition con un filtro
L'errore costoso è ricorrere a FilterExpression per fare il lavoro di una
chiave.
KeyConditionExpression: ChannelRef = :ch
FilterExpression: begins_with(PostedAt, :day)Questo sembra equivalente alla key condition begins_with qui sopra e
restituisce le stesse righe — ma legge l'intera partizione del canale prima,
poi scarta tutto ciò che è fuori dal giorno. Sei fatturato per la lettura
completa.
I filtri non riducono mai il costo di lettura. Girano dopo che DynamoDB ha
contabilizzato gli item, lo stesso footgun di uno Scan
filtrato. Se un predicato può andare nella key condition, è lì che appartiene.
La soluzione è a monte: se un access pattern non può essere espresso come un'uguaglianza di PK più un intervallo di sort key, quello è un segnale di modellazione. O rimodelli la sort key, o aggiungi un indice con chiave per il pattern — vedi GSI vs LSI e single-table design per come disporre le chiavi.
Trappole e prossimi passi
- La partition key è sempre
=. Mai intervalli. Se ti serve un intervallo tra partizioni, hai superato una singolaQuery. - Una condizione sort-key per query. Non puoi mettere in
ANDdue predicati sort-key; scegliBETWEENoppurebegins_with, non entrambi. - Le parole riservate hanno bisogno di alias. Una chiave chiamata
TimestampoNamedeve usareExpressionAttributeNames(#ts), o la query dà errore. (AWS: reserved words) BETWEENè inclusivo. Entrambi gli estremi sono inclusi — progetta i tuoi limiti di conseguenza.
Abbozza le tue key condition nell'expression builder, poi prova DynoTable per eseguirle contro le tue tabelle e guardare la capacità che consumano davvero.