Prisma ORM — Примеры
Пример 1 — Проследите связь от сгенерированного типа
Список операций показывает каждый открытый заказ вместе с адресом электронной почты его клиента, а модели описаны в схеме ниже. Код, идущий следом, обходит связь внутри цикла. Напишите запрос так, чтобы связь приходила со списком, и покажите доказательство, что инструкция была всего одна.
model Order {
id Int @id
status String
customer Customer @relation(fields: [customerId], references: [id])
customerId Int
}
model Customer {
id Int @id
email String
orders Order[]
}
Решение
const orders = await db.order.findMany({
where: { status: "open" },
include: { customer: true }, // разрешается в исходном запросе
});
for (const order of orders) {
notify(order.customer.email); // ни одной инструкции на заказ
}
// журнал сгенерированных инструкций (одна инструкция на весь список):
// SELECT "order".*, "customer".*
// FROM "Order" JOIN "Customer" ON "order"."customerId" = "customer"."id"
// WHERE "order"."status" = 'open'
Файл схемы — источник истины и для типов, и для базы данных, поэтому форма включённой связи входит в тип результата: обращение к свойству компилируется, а журнал инструкций подтверждает, что связь разрешена один раз, а не по разу на строку. Проверить это надёжно можно только по журналу: код выглядел бы почти одинаково и при соединении, и при запросе на каждую строку; обычно же ошибаются иначе — включают в исходный запрос одну связь, а внутри цикла обходят другую, и шаблон возвращается на уровень ниже.
Пример 2 — Переименование, которое сгенерированная миграция удаляет
В схеме поле fullName переименовано в name. Этап генерации создаёт миграцию. Применение её в напечатанном виде потеряло бы каждое существующее имя. Прочитайте миграцию, решите, что она сделает с данными, и исправьте до того, как её применят.
изменение схемы: Customer.fullName -> Customer.name
сгенерированная миграция:
ALTER TABLE "Customer" DROP COLUMN "fullName";
ALTER TABLE "Customer" ADD COLUMN "name" TEXT;
Решение
-- прочитано и исправлено вручную до применения миграции
ALTER TABLE "Customer" RENAME COLUMN "fullName" TO "name";
Инструмент видит лишь то, что одно поле исчезло, а другое появилось, поэтому и выражает переименование как удаление и добавление; отревьюенная версия сохраняет столбец, его значения и любой индекс, который на него ссылался, — и при этом модель с базой всё равно приходят в соответствие. Этап генерации должен выполняться и при сборке. Пропущенная генерация компилируется против устаревшего клиента или падает вовсе. Обычно же к сгенерированной миграции относятся как к артефакту для применения, а не как к коду для чтения.