Key condition expressions de DynamoDB
Una key condition expression es la KeyConditionExpression que pasas a una Query —
la única parte de la petición que DynamoDB usa para encontrar elementos. Todo lo demás
(filtros, proyecciones) se ejecuta después de que la lectura ya está medida.
¿Qué es una key condition expression en DynamoDB?
Una key condition expression es la KeyConditionExpression en una Query que le indica a DynamoDB qué elementos leer. La debe ser una igualdad (PK = :v); la admite un operador de rango — =, <, <=, >, >=, BETWEEN o begins_with. Determina qué se lee y se factura, a diferencia de un filtro.
- La partition key debe ser una igualdad.
PK = :vy nada más — sin rangos, sinbegins_with, sinIN. DynamoDB le aplica un hash para localizar una partición. - La sort key admite un operador de rango.
=,<,<=,>,>=,BETWEENobegins_with— aquí es donde cortas una colección de elementos. - No es un filtro. Una key condition decide qué se lee y se factura; una
FilterExpressionsolo recorta el resultado después de que has pagado la lectura. - Las sort keys están ordenadas por bytes. Los operadores de rango comparan lexicográficamente, así que cómo formateas la cadena de la sort key es tu poder de consulta.
Por qué la partition key está bloqueada a la igualdad
DynamoDB almacena los elementos aplicando un hash a la partition key hacia una partición física. Un hash te da una ubicación, no un rango — así que no hay nada que escanear a lo largo de.
Por eso PK > :v o begins_with(PK, :v) se rechazan de plano. El motor no puede responder
"todas las particiones cuya clave empieza por X" sin leer toda la tabla, que es exactamente
el Scan que está construido para evitar.
Viniendo de SQL, esto parece al revés: WHERE id LIKE 'order%' es trivial en Postgres. En
DynamoDB la partition key es una dirección, no una columna buscable.
La sort key es donde vive el poder
Dentro de una partición, los elementos se almacenan ordenados por la sort key. Ese ordenamiento es lo que explotan los operadores de rango — DynamoDB busca una posición y lee hacia adelante.
| Operador | Lee | Úsalo para |
|---|---|---|
SK = :v | Un elemento exacto | Un hijo específico por su clave |
SK < / <= / > / >= :v | Una porción abierta | "Todo después de este punto" |
SK BETWEEN :a AND :b | Un rango cerrado (inclusivo) | Una ventana acotada — un rango de fechas |
begins_with(SK, :p) | Una porción de prefijo | Un tipo o jerarquía bajo la PK |
No hay LIKE, ni CONTAINS, ni ENDS_WITH sobre la clave. La coincidencia de subcadena y
sufijo no están ordenadas por bytes, así que forzarían una lectura completa — por diseño,
la API no te lo permite. Esas viven en FilterExpression, donde ya has pagado.
(AWS: Key condition expressions)
Un ejemplo desarrollado: mensajes en una app de chat
Digamos que construyes un chat basado en canales. Una tabla, particionada por canal, ordenada por hora del mensaje. Esquema de claves original:
- Partition key
ChannelRef—CH#{channelId} - Sort key
PostedAt— una marca de tiempo ISO-8601,MSG#2026-06-23T14:05:00Z
El prefijo MSG# mantiene las filas de mensaje ordenables y distintas de cualquier otro
tipo de fila que pudieras coubicar bajo el mismo canal (configuración fijada, membresía).
Carga los últimos mensajes de un canal. Solo la partition key, los más nuevos primero:
KeyConditionExpression: ChannelRef = :ch
ExpressionAttributeValues: { ":ch": "CH#general" }
ScanIndexForward: falseScanIndexForward: false recorre la colección ordenada en sentido inverso — la forma
barata de obtener "el más reciente primero" sin ordenar del lado del cliente.
Un día específico con begins_with. Como la marca de tiempo es la sort key y se
almacena como texto, un prefijo de fecha es una porción limpia:
KeyConditionExpression ChannelRef = :ch AND begins_with(PostedAt, :day)
:ch "CH#general"
:day "MSG#2026-06-23"
Eso lee cada mensaje del 2026-06-23 y nada más — DynamoDB busca el prefijo y se detiene cuando se sale del final. Esto solo funciona porque el prefijo es un verdadero ancla a la izquierda de una cadena ordenada por bytes.
Una ventana precisa con BETWEEN. Para "los mensajes durante la hora de las 14:00", un
rango inclusivo gana a un prefijo:
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 es inclusivo en ambos límites, así que elige tus extremos deliberadamente — un
error por uno aquí descarta o duplica silenciosamente un mensaje de borde.
Puedes ensamblar y copiar cualquiera de estas expresiones, con el mapa
ExpressionAttributeValues rellenado por ti, en el
constructor de expresiones de DynamoDB — útil para
acertar la sintaxis de begins_with y BETWEEN a la primera.
Velo en DynoTable
Ejecuta la misma key condition contra una partición de canal real y observa cómo la capacidad consumida se actualiza en vivo, para que puedas confirmar que estás leyendo una porción — no toda la colección.
La trampa: confundir una key condition con un filtro
El error caro es recurrir a FilterExpression para hacer el trabajo de una clave.
KeyConditionExpression: ChannelRef = :ch
FilterExpression: begins_with(PostedAt, :day)Esto parece equivalente a la key condition begins_with de arriba y devuelve las mismas
filas — pero lee toda la partición del canal primero, luego descarta todo lo que está
fuera del día. Se te factura la lectura completa.
Los filtros nunca reducen el coste de lectura. Se ejecutan después de que DynamoDB ha
medido los elementos, el mismo tiro al pie que un Scan filtrado.
Si un predicado puede ir en la key condition, ahí pertenece.
El arreglo está aguas arriba: si un patrón de acceso no puede expresarse como una igualdad de PK más un rango de sort key, eso es una señal de modelado. O remodela la sort key, o añade un índice indexado para el patrón — consulta GSI vs LSI y diseño de tabla única para saber cómo disponer las claves.
Trampas y próximos pasos
- La partition key siempre es
=. Sin rangos, nunca. Si necesitas un rango a través de particiones, has superado lo que una solaQuerypuede dar. - Una condición de sort key por consulta. No puedes hacer
ANDde dos predicados de sort key; eligeBETWEENobegins_with, no ambos. - Las palabras reservadas necesitan alias. Una clave llamada
TimestampoNamedebe usarExpressionAttributeNames(#ts), o la consulta da error. (AWS: reserved words) BETWEENes inclusivo. Ambos extremos coinciden — diseña tus límites en consecuencia.
Redacta tus key conditions en el constructor de expresiones, luego prueba DynoTable para ejecutarlas contra tus propias tablas y ver la capacidad que realmente consumen.