Concepto clave
El schema en Prisma es el corazon de tu aplicacion. Define la estructura de tu base de datos, las relaciones entre entidades y las reglas de validacion. Piensalo como el plano arquitectonico de un edificio: si el plano esta mal disenado, el edificio tendra problemas estructurales. En produccion, un schema bien disenado no solo garantiza la integridad de los datos, sino que tambien optimiza el rendimiento de las queries.
Un schema profesional va mas alla de definir tablas y columnas. Debe considerar: escalabilidad (como crecera tu aplicacion en 2 anos), normalizacion (evitar datos duplicados), y relaciones (uno-a-uno, uno-a-muchos, muchos-a-muchos). Por ejemplo, en una aplicacion de e-commerce, un schema mal disenado podria permitir que un producto tenga multiples precios simultaneos, causando errores en facturacion.
Como funciona en la practica
Vamos a disenar un schema para un sistema de blog con usuarios, posts y comentarios. Primero, identificamos las entidades: User, Post, Comment. Luego, definimos las relaciones: un User puede tener muchos Posts (uno-a-muchos), un Post puede tener muchos Comments (uno-a-muchos), y un Comment pertenece a un User (muchos-a-uno).
Paso 1: Creamos el archivo schema.prisma. Paso 2: Definimos cada modelo con sus campos y tipos. Paso 3: Especificamos las relaciones usando @relation. Paso 4: Aplicamos migraciones con prisma migrate dev. Este proceso transforma nuestro schema en tablas reales en la base de datos.
Codigo en accion
Schema inicial basico (antes de optimizar):
model User {
id Int @id @default(autoincrement())
email String @unique
name String?
posts Post[]
comments Comment[]
}
model Post {
id Int @id @default(autoincrement())
title String
content String?
authorId Int
author User @relation(fields: [authorId], references: [id])
comments Comment[]
}
model Comment {
id Int @id @default(autoincrement())
text String
postId Int
post Post @relation(fields: [postId], references: [id])
userId Int
user User @relation(fields: [userId], references: [id])
}Schema optimizado para produccion (despues de refactorizar):
model User {
id String @id @default(cuid())
email String @unique
name String?
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
posts Post[]
comments Comment[]
@@map("users")
}
model Post {
id String @id @default(cuid())
title String @db.VarChar(255)
content String? @db.Text
published Boolean @default(false)
authorId String
author User @relation(fields: [authorId], references: [id], onDelete: Cascade)
comments Comment[]
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
@@map("posts")
@@index([authorId])
}
model Comment {
id String @id @default(cuid())
text String @db.VarChar(500)
postId String
post Post @relation(fields: [postId], references: [id], onDelete: Cascade)
userId String
user User @relation(fields: [userId], references: [id])
createdAt DateTime @default(now())
@@map("comments")
@@index([postId])
}Errores comunes
- No usar tipos de datos apropiados para produccion: Usar
Intpara IDs en lugar deStringcon@default(cuid())puede causar problemas de escalabilidad. Los CUIDs son mas seguros y escalables. - Olvidar timestamps: No incluir
createdAtyupdatedAtdificulta el debugging y auditoria en produccion. - Relaciones sin cascada: No definir
onDeleteoonUpdatepuede dejar datos huerfanos. Por ejemplo, si borras un usuario, sus posts deberian borrarse automaticamente. - Falta de indices: No agregar
@@indexen campos usados frecuentemente en queries (comoauthorIden Post) ralentiza la aplicacion. - Nombres de tabla por defecto: No usar
@@mappara personalizar nombres de tablas puede llevar a conflictos con convenciones de base de datos existentes.
Checklist de dominio
- ¿Usas CUIDs o UUIDs para IDs en lugar de autoincrementales?
- ¿Incluyes timestamps (
createdAt,updatedAt) en todos tus modelos? - ¿Defines acciones de cascada (
onDelete,onUpdate) en relaciones criticas? - ¿Agregas indices a campos usados en filtros, ordenamientos o joins frecuentes?
- ¿Personalizas nombres de tablas con
@@mappara seguir convenciones de tu equipo? - ¿Usas tipos de base de datos especificos (ej.
@db.VarChar(255)) para controlar el almacenamiento? - ¿Validas que las relaciones reflejen correctamente la logica de negocio (ej. un Comment debe tener un User)?
Refactoriza un Schema de E-commerce para Produccion
Te dan un schema basico para una tienda online. Tu tarea es optimizarlo para produccion aplicando las mejores practicas aprendidas.
- Copia el siguiente schema inicial a un archivo
schema.prisma:
model Product {
id Int @id @default(autoincrement())
name String
price Float
categoryId Int
category Category @relation(fields: [categoryId], references: [id])
}
model Category {
id Int @id @default(autoincrement())
name String
products Product[]
}
model Order {
id Int @id @default(autoincrement())
userId Int
user User @relation(fields: [userId], references: [id])
total Float
}
model User {
id Int @id @default(autoincrement())
email String
orders Order[]
}- Refactoriza el schema para hacerlo listo para produccion. Considera: cambiar IDs a CUIDs, agregar timestamps, definir cascadas, agregar indices, y usar tipos de base de datos especificos.
- Ejecuta
prisma migrate dev --name refactor_schemapara aplicar los cambios (simulado, no necesitas base de datos real). - Verifica que tu schema final no tenga errores comunes listados en la leccion.
- Piensa en que campos son frecuentemente filtrados (ej. categoryId en Product) para agregar indices.
- Usa @db.Decimal para price en lugar de Float para precision monetaria.
- Agrega un campo status en Order para manejar estados como 'pending', 'shipped'.
Evalua tu comprension
Completa el quiz interactivo de arriba para ganar XP.