Что такое Prisma
Prisma — современный ORM для Node.js и TypeScript. Он обеспечивает типобезопасный доступ к базе данных, автоматические миграции и удобный Prisma Client для запросов.
Схема данных
Схема Prisma описывает модели и связи:
// prisma/schema.prisma
generator client {
provider = "prisma-client-js"
}
datasource db {
provider = "postgresql"
url = env("DATABASE_URL")
}
model User {
id String @id @default(uuid())
email String @unique
name String?
password String
role Role @default(USER)
posts Post[]
profile Profile?
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
@@index([email])
}
model Profile {
id String @id @default(uuid())
bio String?
avatar String?
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
userId String @unique
}
model Post {
id String @id @default(uuid())
title String
content String?
published Boolean @default(false)
author User @relation(fields: [authorId], references: [id])
authorId String
categories Category[]
tags String[]
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
@@index([authorId])
@@index([published])
}
model Category {
id String @id @default(uuid())
name String @unique
posts Post[]
}
enum Role {
USER
ADMIN
MODERATOR
}
Миграции
# Создание миграции
npx prisma migrate dev --name init
# Применение миграций в production
npx prisma migrate deploy
# Сброс базы данных (dev only)
npx prisma migrate reset
# Генерация Prisma Client
npx prisma generate
# Просмотр данных в браузере
npx prisma studio
Prisma Client — запросы
import { PrismaClient } from '@prisma/client';
const prisma = new PrismaClient();
// Создание
const user = await prisma.user.create({
data: {
email: 'user@example.com',
name: 'John Doe',
password: hashedPassword,
profile: {
create: {
bio: 'Developer'
}
}
},
include: {
profile: true
}
});
// Чтение
const users = await prisma.user.findMany({
where: {
role: 'ADMIN',
email: { contains: '@company.com' }
},
select: {
id: true,
name: true,
email: true,
_count: { select: { posts: true } }
},
orderBy: { createdAt: 'desc' },
take: 10,
skip: 0
});
// Поиск одного
const user = await prisma.user.findUnique({
where: { email: 'user@example.com' },
include: {
posts: {
where: { published: true },
orderBy: { createdAt: 'desc' }
}
}
});
// Обновление
const updated = await prisma.user.update({
where: { id: userId },
data: {
name: 'New Name',
profile: {
update: { bio: 'Updated bio' }
}
}
});
// Удаление
await prisma.user.delete({
where: { id: userId }
});
Связи между таблицами
// One-to-One (User -> Profile)
const userWithProfile = await prisma.user.findUnique({
where: { id: userId },
include: { profile: true }
});
// One-to-Many (User -> Posts)
const userWithPosts = await prisma.user.findUnique({
where: { id: userId },
include: {
posts: {
where: { published: true },
take: 5
}
}
});
// Many-to-Many (Post <-> Category)
const post = await prisma.post.create({
data: {
title: 'New Post',
content: 'Content...',
authorId: userId,
categories: {
connect: [{ id: cat1Id }, { id: cat2Id }]
}
}
});
// Вложенные запросы
const postsWithAuthors = await prisma.post.findMany({
include: {
author: {
select: { name: true, email: true }
},
categories: true
}
});
Транзакции
// Интерактивная транзакция
const result = await prisma.$transaction(async (tx) => {
// Создаём пользователя
const user = await tx.user.create({
data: { email, name, password }
});
// Создаём профиль
const profile = await tx.profile.create({
data: { userId: user.id, bio: '' }
});
// Если что-то пойдёт не так, всё откатится
return { user, profile };
});
// Batch транзакция
const [users, posts] = await prisma.$transaction([
prisma.user.findMany(),
prisma.post.findMany({ where: { published: true } })
]);
Типизация
import { Prisma, User, Post } from '@prisma/client';
// Типы из схемы
type UserWithPosts = Prisma.UserGetPayload<{
include: { posts: true }
}>;
// Типы для создания
type CreateUserInput = Prisma.UserCreateInput;
// Типы для обновления
type UpdateUserInput = Prisma.UserUpdateInput;
// Использование в функциях
async function createUser(data: CreateUserInput): Promise {
return prisma.user.create({ data });
}
async function getUserWithPosts(id: string): Promise {
return prisma.user.findUnique({
where: { id },
include: { posts: true }
});
}
Оптимизация
// Выбирайте только нужные поля
const users = await prisma.user.findMany({
select: {
id: true,
name: true
// Не загружаем password, posts и т.д.
}
});
// Пагинация с курсором (эффективнее offset)
const posts = await prisma.post.findMany({
take: 10,
cursor: { id: lastPostId },
skip: 1 // Пропускаем курсор
});
// Подсчёт без загрузки данных
const count = await prisma.user.count({
where: { role: 'ADMIN' }
});
// Агрегации
const stats = await prisma.post.aggregate({
_count: true,
_avg: { viewCount: true }
});
Заключение
Prisma упрощает работу с базами данных благодаря типизации, миграциям и удобному API. Схема как единый источник правды, Prisma Client для типобезопасных запросов, Prisma Studio для визуального управления.
Prisma — это не просто ORM, это полноценный инструментарий для работы с данными. Инвестируйте время в изучение схемы и связей.
