Aquí tienes una demo práctica de las operaciones Scan y Query en Amazon DynamoDB usando Python (boto3).
📌 1. Configuración Inicial
Antes de ejecutar los ejemplos, asegúrate de:
✅ Tener AWS CLI configurado con las credenciales correctas.
✅ Instalar boto3 en tu entorno:
pip install boto3
✅ Tener una tabla DynamoDB llamada "Pedidos", con:
- Clave de Partición (PK):
pedido_id
- Clave de Ordenación (SK):
fecha
Ejemplo de datos en la tabla Pedidos:
pedido_id (PK)fecha (SK)clientemontoP0012025-03-10Juan100 USDP0012025-03-12Juan150 USDP0022025-03-11Ana200 USD
📌 2. Conectando a DynamoDB en Python
import boto3
# Conectar con DynamoDB
dynamodb = boto3.resource('dynamodb')
# Definir la tabla
table = dynamodb.Table('Pedidos')
📌 3. SCAN: Buscar Todos los Elementos
🚨 Scan recorre toda la tabla, por lo que es ineficiente en tablas grandes.
response = table.scan()
# Mostrar los resultados
items = response['Items']
for item in items:
print(item)
📌 Salida esperada:
[
{"pedido_id": "P001", "fecha": "2025-03-10", "cliente": "Juan", "monto": 100},
{"pedido_id": "P001", "fecha": "2025-03-12", "cliente": "Juan", "monto": 150},
{"pedido_id": "P002", "fecha": "2025-03-11", "cliente": "Ana", "monto": 200}
]
📌 4. SCAN con Filtros
Podemos aplicar un FilterExpression para reducir los resultados.
Ejemplo: Buscar pedidos con monto mayor a 120 USD.
response = table.scan(
FilterExpression="monto > :monto",
ExpressionAttributeValues={":monto": 120}
)
items = response['Items']
print(items)
📌 Salida esperada:
[
{"pedido_id": "P001", "fecha": "2025-03-12", "cliente": "Juan", "monto": 150},
{"pedido_id": "P002", "fecha": "2025-03-11", "cliente": "Ana", "monto": 200}
]
❗ Nota: Scan sigue recorriendo toda la tabla, solo filtra los datos después de leerlos.
📌 5. QUERY: Búsqueda Eficiente
🚀 Query es más rápido que Scan, ya que solo busca los elementos con una clave de partición específica.
🔹 Ejemplo 1: Buscar pedidos de P001
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}
]
🔹 Ejemplo 2: Query con Rango de Fechas
Si queremos pedidos de "P001" a partir del 2025-03-11, usamos rango en SK:
response = table.query(
KeyConditionExpression="pedido_id = :pedido AND fecha >= :fecha",
ExpressionAttributeValues={
":pedido": "P001",
":fecha": "2025-03-11"
}
)
items = response['Items']
print(items)
📌 Salida esperada:
[
{"pedido_id": "P001", "fecha": "2025-03-12", "cliente": "Juan", "monto": 150}
]
🔹 Ejemplo 3: Query con Filtros
Podemos agregar filtros en atributos secundarios (ej. monto > 120), aunque DynamoDB sigue trayendo todos los elementos de la PK antes de filtrarlos.
response = table.query(
KeyConditionExpression="pedido_id = :pedido",
FilterExpression="monto > :monto",
ExpressionAttributeValues={
":pedido": "P001",
":monto": 120
}
)
items = response['Items']
print(items)
📌 Salida esperada:
[
{"pedido_id": "P001", "fecha": "2025-03-12", "cliente": "Juan", "monto": 150}
]
📌 6. Paginación en Scan y Query
Si hay muchos resultados, DynamoDB devuelve solo 1 MB de datos a la vez y usa LastEvaluatedKey para continuar.
items = []
response = table.scan()
while "LastEvaluatedKey" in response:
items.extend(response['Items'])
response = table.scan(ExclusiveStartKey=response["LastEvaluatedKey"])
print(items)
Lo mismo aplica para Query:
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)
📌 7. Query en Índices Secundarios (GSI)
Si queremos consultar por otro atributo (ej. cliente), necesitamos un Índice Secundario Global (GSI).
Ejemplo: GSI con PK = cliente y SK = fecha.
response = table.query(
IndexName="ClienteIndex",
KeyConditionExpression="cliente = :cliente",
ExpressionAttributeValues={":cliente": "Juan"}
)
items = response['Items']
print(items)
📌 Conclusión
✅ Usa Query en lugar de Scan siempre que sea posible.
✅ Filtra con KeyConditionExpression para optimizar búsquedas.
✅ Usa FilterExpression solo si necesitas filtrar después de consultar.
✅ Usa paginación (LastEvaluatedKey) para manejar grandes volúmenes de datos.
✅ Aprovecha los Índices Secundarios (GSI, LSI) para mejorar rendimiento.