Saltar al contenido

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

prisma
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

  1. Define producto, pedido y línea.

  2. Decide qué valores deben quedar históricos.

  3. Añade cantidades positivas y relaciones obligatorias.

  4. 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.

Tablas de clientes y pedidos: INNER JOIN conserva coincidencias y LEFT JOIN conserva también a Luis sin pedidos.
CursaloMapa de práctica
Relacionar tablas sin perder filas

Una 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:

  1. Define el modelo Usuario con campos como id, email, nombre y una relación a Pedido.
  2. Crea el modelo Producto con id, nombre, precio, stock y categoría.
  3. Modela Pedido con id, fecha, estado y relaciones a Usuario y DetallePedido.
  4. 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

  1. ¿Definiste todos los modelos necesarios (Usuario, Producto, Pedido, DetallePedido) con sus campos básicos?
  2. ¿Estableciste las relaciones correctamente (uno a muchos, muchos a muchos) usando claves foráneas?
  3. ¿Agregaste índices a campos como email y categoría para optimizar consultas?
  4. ¿Usaste tipos de datos específicos (ej., @db.Decimal para precios) en lugar de tipos genéricos?
  5. ¿Incluiste campos de auditoría como createdAt y updatedAt en modelos críticos?
  6. ¿Validaste que el schema permita operaciones comunes como crear un pedido con múltiples productos?
  7. ¿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:

  1. Crea un nuevo modelo llamado Resena con los siguientes campos: id, contenido, calificacion (del 1 al 5), usuarioId, productoId, y fechacreacion.
  2. 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).
  3. Agrega validaciones: calificacion debe ser un entero entre 1 y 5, y contenido debe tener un máximo de 500 caracteres.
  4. Implementa un índice compuesto en usuarioId y productoId para evitar que un usuario deje múltiples reseñas para el mismo producto.
  5. Genera una migración usando npx prisma migrate dev --name add_resenas y 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.

01 / ELEGIR UNA RUTA

El próximo paso

Aprende IA mientras construyes algo que sí necesitas.

Empieza por el curso inicial o explora el catálogo para encontrar una práctica alineada con tu trabajo.