Lección 3 de 17 · Lectura y práctica
Práctica: Crear un Schema para una API de E-commerce
Tipo de lección: VideoConcepto claveDiseñar un schema para una API de e-commerce en producción requiere pensar en escalabilidad, relaciones entre entidades y validaciones desde el inicio. Imagina que estás construyendo un centro.
Del concepto a la práctica
Taller de esta lección
En un comercio, el precio vigente y el precio de una línea de pedido no significan lo mismo. El producto puede cambiar de precio, pero una compra histórica debe conservar el importe aplicado. Por eso OrderItem almacena una copia monetaria de la línea.
Ejemplo resuelto
model OrderItem {
id Int @id @default(autoincrement())
orderId Int
productId Int
quantity Int
unitCents Int
order Order @relation(fields: [orderId], references: [id])
product Product @relation(fields: [productId], references: [id])
@@unique([orderId, productId])
}Con 2 unidades a 1250 céntimos, el importe es 2 * 1250 = 2500 céntimos.
Este modelo requiere Order.items y Product.items como relaciones inversas. La restricción unique presupone UNA línea por producto en cada pedido; si vendes variantes diferentes usa identidad de variante, no fusiones cantidades indiscriminadamente. Valida quantity>=1 yunitCents>=0, añade CHECK de base cuando corresponda y fija monedaEUR para los ejercicios. Int no expresa por sí solo positividad ni evita desbordamiento de totales; calcula con un rango/representación adecuados.
Pruébalo
Define producto, pedido y línea.
Decide qué valores deben quedar históricos.
Añade cantidades positivas y relaciones obligatorias.
Calcula el total desde las líneas almacenadas.
Comprueba tu resultado
El pedido anterior conserva 2500 céntimos aunque el producto cambie después.
Error frecuente: guardar precio como Float. Corrígelo con enteros en la unidad monetaria menor o un decimal apropiado al motor.
Ejercicio: inserta tres líneas con cantidades 1, 2 y 3 y precios 800, 1250 y 400; el total esperado es 4500 céntimos.

Mapa de prácticaUna clave conecta cada pedido con su cliente. INNER JOIN devuelve las coincidencias y puede producir varias filas por cliente. LEFT JOIN conserva también los clientes sin pedido y representa los campos ausentes con NULL.
Ver la infografía en tamaño completo ↗Tipo de lección: Video
Concepto clave
Diseñar un schema para una API de e-commerce en producción requiere pensar en escalabilidad, relaciones entre entidades y validaciones desde el inicio. Imagina que estás construyendo un centro comercial digital: necesitas tiendas (productos), clientes (usuarios), transacciones (pedidos) y un sistema de inventario que funcione en tiempo real. En Prisma, el schema define la estructura de tu base de datos usando un lenguaje declarativo que luego se traduce a SQL mediante migraciones.
La clave está en modelar las relaciones correctamente. Por ejemplo, un usuario puede tener múltiples pedidos, y cada pedido puede contener varios productos. Esto se representa con relaciones uno a muchos y muchos a muchos. En producción, debes evitar diseños que generen consultas ineficientes, como anidaciones excesivas o falta de índices en campos frecuentemente consultados.
Cómo funciona en la práctica
Vamos a crear un schema básico para un e-commerce con estas entidades: Usuario, Producto, Pedido y DetallePedido. Sigue estos pasos:
- Define el modelo Usuario con campos como id, email, nombre y una relación a Pedido.
- Crea el modelo Producto con id, nombre, precio, stock y categoría.
- Modela Pedido con id, fecha, estado y relaciones a Usuario y DetallePedido.
- Implementa DetallePedido como tabla de unión para la relación muchos a muchos entre Pedido y Producto, incluyendo cantidad y precioUnitario.
Antes de codificar, piensa en los índices: por ejemplo, agrega un índice único al email del usuario para evitar duplicados y mejorar búsquedas. En producción, esto reduce tiempos de consulta significativamente.
Código en acción
Aquí tienes un ejemplo funcional del schema.prisma:
// Modelo Usuario
model Usuario {
id Int @id @default(autoincrement())
email String @unique
nombre String
pedidos Pedido[]
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
}
// Modelo Producto
model Producto {
id Int @id @default(autoincrement())
nombre String
precio Float
stock Int @default(0)
categoria String
detalles DetallePedido[]
}
// Modelo Pedido
model Pedido {
id Int @id @default(autoincrement())
fecha DateTime @default(now())
estado String @default("pendiente")
usuarioId Int
usuario Usuario @relation(fields: [usuarioId], references: [id])
detalles DetallePedido[]
}
// Modelo DetallePedido (tabla de unión)
model DetallePedido {
id Int @id @default(autoincrement())
pedidoId Int
productoId Int
cantidad Int @default(1)
precioUnitario Float
pedido Pedido @relation(fields: [pedidoId], references: [id])
producto Producto @relation(fields: [productoId], references: [id])
@@unique([pedidoId, productoId])
}Ahora, mejoremos el schema para producción agregando validaciones y un índice compuesto:
// Refactorización: Agregar validaciones e índices
model Usuario {
id Int @id @default(autoincrement())
email String @unique @db.VarChar(255)
nombre String @db.VarChar(100)
pedidos Pedido[]
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
@@index([email]) // Índice para búsquedas rápidas
}
model Producto {
id Int @id @default(autoincrement())
nombre String @db.VarChar(200)
precio Float @db.Decimal(10, 2)
stock Int @default(0)
categoria String @db.VarChar(50)
detalles DetallePedido[]
@@index([categoria]) // Índice para filtrar por categoría
}Errores comunes
- Olvidar relaciones bidireccionales: En Prisma, si defines una relación en un modelo, debes definirla en el otro. Por ejemplo, si Usuario tiene pedidos, Pedido debe tener un campo usuarioId y una relación a Usuario.
- No usar tipos de datos apropiados para producción: Evita String sin límites; usa @db.VarChar(length) para controlar el almacenamiento y mejorar el rendimiento.
- Ignorar índices en campos frecuentemente consultados: Campos como email o categoría deben tener índices para acelerar las queries en grandes volúmenes de datos.
- Diseñar relaciones muchos a muchos sin tabla de unión explícita: En e-commerce, necesitas almacenar datos adicionales como cantidad y precio en DetallePedido; no uses la relación implícita de Prisma en este caso.
- No planificar migraciones desde el inicio: Cambiar el schema después de desplegar requiere migraciones cuidadosas; prueba siempre en un entorno de staging primero.
Checklist de dominio
- ¿Definiste todos los modelos necesarios (Usuario, Producto, Pedido, DetallePedido) con sus campos básicos?
- ¿Estableciste las relaciones correctamente (uno a muchos, muchos a muchos) usando claves foráneas?
- ¿Agregaste índices a campos como email y categoría para optimizar consultas?
- ¿Usaste tipos de datos específicos (ej., @db.Decimal para precios) en lugar de tipos genéricos?
- ¿Incluiste campos de auditoría como createdAt y updatedAt en modelos críticos?
- ¿Validaste que el schema permita operaciones comunes como crear un pedido con múltiples productos?
- ¿Probaste el schema generando una migración y ejecutándola en una base de datos local?
Extiende el Schema para Incluir Reseñas de Productos
En este ejercicio, ampliarás el schema de e-commerce para soportar reseñas de productos, una funcionalidad común en plataformas de comercio electrónico. Sigue estos pasos:
- Crea un nuevo modelo llamado Resena con los siguientes campos: id, contenido, calificacion (del 1 al 5), usuarioId, productoId, y fechacreacion.
- Establece las relaciones: una Resena pertenece a un Usuario y a un Producto. Asegúrate de que Usuario y Producto tengan campos para acceder a sus reseñas (ej., resenas en Usuario y Producto).
- Agrega validaciones: calificacion debe ser un entero entre 1 y 5, y contenido debe tener un máximo de 500 caracteres.
- Implementa un índice compuesto en usuarioId y productoId para evitar que un usuario deje múltiples reseñas para el mismo producto.
- Genera una migración usando
npx prisma migrate dev --name add_resenasy verifica que no haya errores.
Al final, tu schema debe permitir consultas como "obtener todas las reseñas de un producto con sus usuarios" de forma eficiente.
Pistas
- Recuerda que en Prisma, las relaciones se definen en ambos modelos involucrados.
- Usa @db.VarChar(500) para limitar el contenido de la reseña.
- Considera agregar un campo de estado (ej., 'activa' o 'eliminada') para manejar moderación en producción.
Evalua tu comprension
Completa el quiz interactivo de arriba para ganar XP.
Sigue con Prisma ORM Profesional: Schemas, Migraciones y Queries Optimizadas para Producción
Esta lección forma parte de un curso de Cursalo. Revisa su programa y elige entre la compra individual o el acceso a toda la escuela.
Si ya tenías acceso a este curso, entra con tu cuenta: tus derechos y tu progreso se conservan. No necesitas comprarlo de nuevo.