Intermedio5 min di lettura

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 = :v e nient'altro — niente intervalli, niente begins_with, niente IN. DynamoDB ne calcola l'hash per individuare una partizione.
  • La sort key prende un operatore di intervallo. =, <, <=, >, >=, BETWEEN, o begins_with — è qui che affetti una item collection.
  • Non è un filtro. Una key condition decide cosa viene letto e fatturato; una FilterExpression taglia 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.

OperatoreLeggeUsalo per
SK = :vUn item esattoUn figlio specifico tramite la sua chiave
SK < / <= / > / >= :vUna fetta aperta da un lato"Tutto dopo questo punto"
SK BETWEEN :a AND :bUn intervallo chiuso (inclusivo)Una finestra limitata — un intervallo di date
begins_with(SK, :p)Una fetta per prefissoUn 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 ChannelRefCH#{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:  false

ScanIndexForward: 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 singola Query.
  • Una condizione sort-key per query. Non puoi mettere in AND due predicati sort-key; scegli BETWEEN oppure begins_with, non entrambi.
  • Le parole riservate hanno bisogno di alias. Una chiave chiamata Timestamp o Name deve usare ExpressionAttributeNames (#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.

Aggiornato