📌 Operaciones Query en Amazon DynamoDB
Amazon DynamoDB es una base de datos NoSQL diseñada para manejar datos con acceso rápido y escalable. Una de las formas más eficientes de recuperar datos es mediante la operación Query, que permite buscar elementos con base en la clave de partición y, opcionalmente, la clave de ordenación.
1️⃣ ¿Qué es Query en DynamoDB?
Query se usa para recuperar elementos rápidamente usando el índice primario o un índice secundario (GSI o LSI).
🔹 Diferencias clave entre Scan y Query
OperaciónDescripciónEficienciaScanRecorre toda la tabla, aplicando un filtro opcional.🚨 Ineficiente en tablas grandes.QueryBusca por clave de partición (PK) y opcionalmente por clave de ordenación (SK).🚀 Rápida y optimizada.
📌 Siempre que sea posible, usa Query en lugar de Scan para mejorar el rendimiento.
2️⃣ Ejecutando un Query en DynamoDB
Para ejecutar una consulta con Query, necesitamos conocer:
✅ Clave de Partición (PK): Obligatoria.
✅ Clave de Ordenación (SK): Opcional, pero permite búsquedas más refinadas.
Ejemplo de Query
Supongamos que tenemos la siguiente tabla Pedidos con las claves:
pedido_id (PK)fecha (SK)clientemontoP0012025-03-10Juan100 USDP0012025-03-12Juan150 USDP0022025-03-11Ana200 USD
🔹 Consultar los pedidos de "P001"
import boto3
dynamodb = boto3.resource('dynamodb')
table = dynamodb.Table('Pedidos')
response = table.query(
KeyConditionExpression="pedido_id = :pedido",
ExpressionAttributeValues={":pedido": "P001"}
)
items = response['Items']
print(items)
📌 Salida esperada:
[
{"pedido_id": "P001", "fecha": "2025-03-10", "cliente": "Juan", "monto": 100},
{"pedido_id": "P001", "fecha": "2025-03-12", "cliente": "Juan", "monto": 150}
]
🔹 ¿Qué está pasando aquí?
- Se está buscando todos los elementos donde
pedido_id = 'P001'.
- DynamoDB devuelve solo esos registros, sin escanear toda la tabla.
3️⃣ Filtrando resultados en Query
Podemos agregar condiciones en la clave de ordenación (SK) o en otros atributos con filtros.
✅ 1. Usar operadores en la SK (rango de fechas)
Si queremos pedidos después del 2025-03-11:
response = table.query(
KeyConditionExpression="pedido_id = :pedido AND fecha >= :fecha",
ExpressionAttributeValues={
":pedido": "P001",
":fecha": "2025-03-11"
}
)
📌 Salida esperada:
[
{"pedido_id": "P001", "fecha": "2025-03-12", "cliente": "Juan", "monto": 150}
]
✅ 2. Filtrar por atributos secundarios (FilterExpression)
Si queremos pedidos de P001 con monto mayor a 120 USD:
response = table.query(
KeyConditionExpression="pedido_id = :pedido",
FilterExpression="monto > :monto",
ExpressionAttributeValues={
":pedido": "P001",
":monto": 120
}
)
📌 Salida esperada:
[
{"pedido_id": "P001", "fecha": "2025-03-12", "cliente": "Juan", "monto": 150}
]
❗ IMPORTANTE:
FilterExpression NO reduce el número de elementos escaneados, solo filtra después de la búsqueda.
- Es más eficiente hacer búsquedas con
KeyConditionExpression.
4️⃣ Ordenamiento y Paginación en Query
✅ 1. Orden Ascendente o Descendente
Por defecto, DynamoDB ordena los resultados en orden ascendente por la clave de ordenación (SK).
Si queremos orden descendente:
response = table.query(
KeyConditionExpression="pedido_id = :pedido",
ExpressionAttributeValues={":pedido": "P001"},
ScanIndexForward=False # Activa el orden descendente
)
📌 Salida esperada (ordenado de más reciente a más antiguo):
[
{"pedido_id": "P001", "fecha": "2025-03-12", "cliente": "Juan", "monto": 150},
{"pedido_id": "P001", "fecha": "2025-03-10", "cliente": "Juan", "monto": 100}
]
✅ 2. Paginación con LastEvaluatedKey
Si la consulta devuelve más de 1 MB de datos, DynamoDB paginará los resultados.
items = []
response = table.query(
KeyConditionExpression="pedido_id = :pedido",
ExpressionAttributeValues={":pedido": "P001"}
)
while "LastEvaluatedKey" in response:
items.extend(response['Items'])
response = table.query(
KeyConditionExpression="pedido_id = :pedido",
ExpressionAttributeValues={":pedido": "P001"},
ExclusiveStartKey=response["LastEvaluatedKey"]
)
print(items)
📌 Beneficio: Se puede manejar grandes volúmenes de datos sin bloquear la memoria.
5️⃣ Query en Índices Secundarios
Si queremos consultar por un atributo que no es la clave de partición, podemos usar:
✅ Índices Secundarios Locales (LSI) → Misma PK, diferente SK.
✅ Índices Secundarios Globales (GSI) → Diferente PK y SK.
Ejemplo: Si la tabla Pedidos tiene un GSI con cliente como PK y fecha como SK, podemos buscar todos los pedidos de un cliente:
response = table.query(
IndexName="ClienteIndex",
KeyConditionExpression="cliente = :cliente",
ExpressionAttributeValues={":cliente": "Juan"}
)
📌 Beneficio: Permite búsquedas rápidas sin escanear la tabla principal.
📌 Conclusión
✅ Usa Query siempre que sea posible, ya que es mucho más eficiente que Scan.
✅ Aprovecha los índices secundarios (GSI y LSI) para optimizar búsquedas sin usar Scan.
✅ Filtra con KeyConditionExpression en lugar de FilterExpression para reducir la cantidad de elementos escaneados.
✅ Usa paginación con LastEvaluatedKey si la consulta devuelve muchos resultados.
✅ Ordena con ScanIndexForward=False si necesitas datos en orden descendente.