Concepto clave
Diseñar un schema en Prisma es como crear los planos de un edificio antes de construirlo. Define la estructura de tu base de datos, incluyendo tablas (modelos), columnas (campos) y cómo se conectan entre sí (relaciones). En producción, un buen schema no solo organiza los datos, sino que también previene errores mediante validaciones y optimiza el rendimiento desde el inicio.
Imagina que estás diseñando una plataforma de e-commerce. Necesitas modelos para Usuario, Producto y Pedido. Las relaciones entre ellos (un usuario puede tener muchos pedidos, un pedido puede contener varios productos) son cruciales para consultas eficientes. Las validaciones aseguran que, por ejemplo, el precio de un producto nunca sea negativo o que un email tenga formato correcto, evitando datos corruptos que podrían romper tu aplicación en producción.
Cómo funciona en la práctica
Primero, defines tus modelos en el archivo schema.prisma. Cada modelo se traduce a una tabla en la base de datos. Para relaciones, usas campos especiales que conectan modelos, como @relation. Las validaciones se aplican directamente en los campos con atributos como @unique, @default, o restricciones de tipo.
Paso a paso: 1) Identifica las entidades principales de tu aplicación (ej: Usuario, Producto). 2) Define los campos de cada modelo con tipos de datos precisos (ej: String, Int, DateTime). 3) Establece relaciones usando claves foráneas implícitas o explícitas. 4) Añade validaciones para integridad de datos. 5) Ejecuta prisma migrate dev para generar migraciones que aplican el schema a la base de datos.
Código en acción
Aquí un ejemplo funcional para un sistema de blog con usuarios y posts, incluyendo relaciones y validaciones básicas:
// schema.prisma
generator client {
provider = "prisma-client-js"
}
datasource db {
provider = "postgresql"
url = env("DATABASE_URL")
}
model User {
id Int @id @default(autoincrement())
email String @unique
name String?
posts Post[]
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
}
model Post {
id Int @id @default(autoincrement())
title String @db.VarChar(200)
content String?
published Boolean @default(false)
author User @relation(fields: [authorId], references: [id])
authorId Int
createdAt DateTime @default(now())
}
Ahora, mejorémoslo para producción añadiendo validaciones avanzadas y una relación muchos-a-muchos para etiquetas:
// schema.prisma mejorado
model User {
id Int @id @default(autoincrement())
email String @unique @db.VarChar(255)
name String? @db.VarChar(100)
posts Post[]
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
@@map("users") // Nombre personalizado de tabla
}
model Post {
id Int @id @default(autoincrement())
title String @db.VarChar(200)
content String? @db.Text
published Boolean @default(false)
author User @relation(fields: [authorId], references: [id], onDelete: Cascade)
authorId Int
tags Tag[]
createdAt DateTime @default(now())
@@map("posts")
}
model Tag {
id Int @id @default(autoincrement())
name String @unique @db.VarChar(50)
posts Post[]
@@map("tags")
}
Errores comunes
- No definir relaciones correctamente: Olvidar el campo
authorIden Post o no usar@relationcausa errores en migraciones. Siempre incluye ambos lados de la relación. - Validaciones insuficientes: Usar
Stringsin límites (como@db.VarChar(255)) puede llevar a datos excesivamente largos en producción. Especifica restricciones de base de datos. - Ignorar eliminación en cascada: En relaciones, no configurar
onDelete(ej:CascadeoSetNull) puede dejar datos huérfanos. Define el comportamiento según tu lógica de negocio. - No usar migraciones incrementalmente Hacer cambios grandes en el schema de una vez complica el rollback. Aplica migraciones pequeñas y frecuentes.
- Olvidar índices para rendimiento: En producción, campos usados frecuentemente en consultas (como
authorId) deben tener índices. Añade@@indexen modelos.
Checklist de dominio
- ¿Definiste todos los modelos necesarios para tu aplicación con campos tipados correctamente?
- ¿Estableciste relaciones (uno-a-muchos, muchos-a-muchos) usando
@relationy campos de clave foránea? - ¿Añadiste validaciones clave como
@unique,@default, y restricciones de base de datos (ej:@db.VarChar(255))? - ¿Configuraste comportamientos de eliminación (ej:
onDelete: Cascade) para mantener la integridad referencial? - ¿Usaste
@@mappara personalizar nombres de tablas si es necesario para convenciones de tu equipo? - ¿Consideraste añadir índices con
@@indexpara campos consultados frecuentemente? - ¿Probaste el schema generando una migración con
prisma migrate devy verificando que no haya errores?
Diseña un Schema para un Sistema de Reservas de Hotel
En este ejercicio, crearás un schema Prisma para un sistema de reservas de hotel en producción. Sigue estos pasos:
- Crea un nuevo proyecto Node.js e instala Prisma con
npm install prisma @prisma/client. - Inicializa Prisma con PostgreSQL:
npx prisma init. - En
schema.prisma, define los siguientes modelos con relaciones y validaciones:- Habitacion: id, numero (único), tipo (ej: 'individual', 'doble'), precioPorNoche, reservas (relación).
- Cliente: id, email (único), nombre, telefono, reservas (relación).
- Reserva: id, fechaEntrada, fechaSalida, total, cliente (relación), habitacion (relación).
- Añade validaciones: precioPorNoche debe ser positivo, email con formato, fechas válidas.
- Configura la relación entre Reserva y Habitacion como muchos-a-uno, y entre Reserva y Cliente como muchos-a-uno.
- Ejecuta
npx prisma migrate dev --name initpara generar y aplicar la migración. - Verifica que no haya errores y que las tablas se creen correctamente en tu base de datos.
- Usa tipos como @db.Decimal para precioPorNoche para precisión en moneda.
- Considera añadir un campo @default(now()) para fecha de creación en Reserva.
- Para la relación, asegúrate de incluir habitacionId y clienteId en el modelo Reserva.
Evalua tu comprension
Completa el quiz interactivo de arriba para ganar XP.