IlmHamroh
JavaScript Full-stack/27-qism. Ma'lumotlar bazasi chuqur: Postgres, ORM, Mongo, Redis21/65-dars16 daqiqa
Mundarija (29)

Prisma modellar va atributlar: @id, @default, @map, @@index, BigInt, Decimal va enum

Qisqacha: Prisma'da har jadval — model, har ustun — maydon (turi va atributlari bilan). Bitta @ — maydon atributi (@id, @default, @unique, @map, @db.Timestamptz(6)), ikkita @@ — model atributi (@@unique, @@index, @@map). Muhim farq: @default(uuid(7)) va @updatedAt qiymatni Prisma Client qo'yadi, bazada DEFAULT bo'lmaydi; now() va autoincrement() esa bazaning o'zida. BigInt JS'da bigint, Decimal — maxsus obyekt: ikkalasi ham JSON.stringify va arifmetikada ehtiyot talab qiladi.

Bu darsda

  • db pull natijasini Prisma uslubiga keltirasiz: model Vazifa, maydon egasiId, bazada nomlar o'zgarmaydi.
  • Maydon va model atributlarini o'qiysiz va qaysi biri bazada, qaysi biri client'da ishlashini bilasiz.
  • BigInt, Decimal, DateTime, Json va enum JS'ga qanday kelishini ko'rasiz.
  • Indeks va noyoblikni sxemada bazadagi nomi bilan e'lon qilasiz.
  • Prisma ifodalay olmaydigan narsalarni (trigger qiymatlari, generated ustun) sxemada to'g'ri belgilaysiz.

Oldin bilishingiz kerak: Prisma 7: o'rnatish va arxitektura, PostgreSQL ma'lumot turlari, Primary key tanlovi, Pul, miqdor va enum'larni modellash.

1. Nega bu kerak?

Oldingi darsda db pull bazadan sxema yasab berdi. Lekin uning natijasi TypeScript kodida g'alati ko'rinadi:

ts
await db.vazifalar.findMany({ where: { egasi_id: 1n } });

Model nomi ko'plikda (vazifalar), maydon nomi ilon_uslubida (egasi_id) — JavaScript'da esa odatiy uslub camelCase va birlik: db.vazifa.findMany({ where: { egasiId: 1n } }). Bazadagi nomlarni o'zgartirish esa mumkin emas: ularni 26-qismdagi SQL, trigger'lar va pg ombori ishlatadi.

Prisma buni xarita bilan hal qiladi: kodda bir nom, bazada boshqa nom (@map, @@map). Bu darsda shunday "tarjima"ni va sxema tilining boshqa qismlarini ko'ramiz — ular aniq bo'lmasa, bigint xatolari, yo'qolgan indekslar va "nega vaqt yangilanmadi" degan savollar keladi.

O'xshatish: pasport va laqab. Bazada rasmiy ism — vazifalar.egasi_id, kodda esa hamma uni vazifa.egasiId deb chaqiradi. Odam bitta, @map — "laqabi shu" degan yozuv.

Diqqat: Kanon sxemasi — holat 20 (prisma/schema.prisma), Prisma 7.10.1, PostgreSQL 18.6; JS'dagi turlar — kanon tajribasidan. Kanonda yo'q atributlarni (uuid(7), Decimal, @updatedAt, @unique) biz alohida namuna modelda sinadik: Prisma 7.10.1, PostgreSQL 17.6, Node 24.21.0 — "biz ishga tushirdik".

2. Model va maydon

2.1 Tuzilishi

Kanondagi Teg modeli — eng qisqasi:

ts
model Teg {
  id      BigInt @id @default(autoincrement())
  egasiId BigInt @map("egasi_id")
  /// "#" bilan, kichik harfda (CHECK) — trigger matndan yozadi
  nom     String

  egasi         Foydalanuvchi @relation(fields: [egasiId], references: [id], onDelete: Cascade, onUpdate: NoAction)
  vazifaTeglari VazifaTegi[]

  @@unique([egasiId, nom], map: "teglar_egasi_id_nom_key")
  @@map("teglar")
}

(Prisma sxema tilini sayt alohida bo'yamaydi; uzun relation qatori kanondagidek qoldirildi.) Har qator — nom Tur atributlar:

  • id BigInt @id @default(autoincrement()) — maydon id, turi BigInt, u birlamchi kalit va qiymatini baza beradi.
  • egasiId BigInt @map("egasi_id") — kodda egasiId, bazada egasi_id.
  • /// — hujjat izohi: generatsiya qilingan TypeScript'da maydon ustida ko'rinadi (muharrir maslahatida). Oddiy // izohi esa faqat sxemada qoladi.
  • egasi va vazifaTeglari — relation maydonlari: bazada ustun emas, Prisma'ga "bu model qaysi modellar bilan bog'langan" degan ma'lumot. Ular Prisma: relations darsida.
  • @@unique, @@map — butun modelga tegishli atributlar.

2.2 Nomlash qoidasi (kanon)

Nima Kodda Bazada Qanday
model Vazifa (PascalCase, birlik) vazifalar @@map("vazifalar")
maydon yaratilganVaqt (camelCase) yaratilgan_vaqt @map("yaratilgan_vaqt")
enum Ustuvorlik ustuvorlik @@map("ustuvorlik")
indeks — vazifalar_egasi_id_idx map: "…"

Client'da model nomi kichik harfdan: Vazifa → db.vazifa, Foydalanuvchi → db.foydalanuvchi. Bazada hech narsa o'zgarmaydi — xarita faqat Prisma'ning ichida.

Tekshirib ko'ring: Kanon Vazifa modelidan @@map("vazifalar") ni olib tashlasa, Prisma qaysi jadvalni qidiradi?

Javob

Vazifa jadvalini (katta harf bilan, qo'shtirnoqda — "public"."Vazifa"). Bazada bunday jadval yo'q, so'rov "jadval mavjud emas" xatosi bilan yiqiladi. Migratsiya vositasi esa bunday sxemadan yangi Vazifa jadvalini yaratishga urinadi — shuning uchun mavjud bazada @@map va @map hech qachon unutilmaydi.

3. Skalyar turlar va JS

3.1 Moslik jadvali

Prisma PostgreSQL (sukut) JS'da
Int integer number
BigInt bigint bigint (1n)
Float double precision number
Decimal numeric(65,30) Decimal obyekti
String text string
Boolean boolean boolean
DateTime timestamp(3) Date
Json jsonb obyekt / massiv / son

Sukut tur sizga to'g'ri kelmasa, native type atributi bilan aniqlaysiz: @db.Timestamptz(6), @db.Decimal(12, 2), @db.Uuid, @db.Text. Kanonda hamma vaqt ustunlari DateTime @db.Timestamptz(6) — chunki 26-qismda timestamptz tanlagan edik (SQL'da sana va vaqt zonalari), Prisma'ning sukut timestamp(3) i esa vaqt zonasisiz.

3.2 Kanon tajribasi: turlar JS'da

Kanon namuna bazadan bitta vazifa va foydalanuvchi sozlamalarini o'qidi:

text
bigint 1 true yuqori {"til":"uz-Latn","mavzu":"qorongi","bildirishnoma":{"email":true,"telegram":true}}
JSON.stringify(bigint): Do not know how to serialize a BigInt

Qatorma-qator: id turi — bigint, qiymati 1; muddat instanceof Date — true; ustuvorlik — oddiy satr "yuqori" (enum JS'da satr); sozlamalar (Json) — tayyor obyekt. Ikkinchi qator — eng ko'p uchraydigan xato: JSON.stringify bigint ni bilmaydi. Express javobida res.json(vazifa) aynan shu xato bilan yiqiladi.

Prisma yuborgan SQL'da qiziq detal bor (kanon):

text
SQL: SELECT … "public"."vazifalar"."ustuvorlik"::text, … WHERE "public"."vazifalar"."id" = $1

Enum ustuni ::text bilan o'qiladi — Prisma enum'ni satr sifatida oladi va o'zi tekshiradi.

3.3 BigInt bilan yashash

Ikki yo'l bor:

  1. Chegarada aylantirish — API javobidan oldin Number(v.id). Xavfsiz, agar qiymat Number.MAX_SAFE_INTEGER (2⁵³ − 1) dan kichik bo'lsa. Kanon PrismaOmbori shunday qiladi: son() yordamchisi tekshiradi va katta bo'lsa xato beradi.
  2. Sxemada Int — agar jadval hech qachon 2 milliarddan oshmasa. Lekin bazadagi tur bigint bo'lsa, Prisma uni BigInt deb introspection qiladi — turni faqat sxemada o'zgartirib bo'lmaydi.

Kichik namuna — brauzerda ishlaydi:

js
const id = 9007199254740993n; // 2^53 + 1
console.log(Number(id));                 // 9007199254740992
console.log(Number.isSafeInteger(Number(id))); // false
console.log(Number(48n) + 1);            // 49

Birinchi qatorda 1 yo'qoldi: number 2⁵³ dan katta butun sonni aniq saqlay olmaydi. Shuning uchun "jim Number()" emas — tekshiruv bilan aylantirish (2-mashq).

4. @default: kim qiymat beradi

4.1 Bazada yoki client'da

Bu darsning eng muhim jadvali:

Atribut Qiymatni kim beradi Bazada DEFAULT bormi
@default(autoincrement()) baza (sequence/identity) ha
@default(now()) baza ha (CURRENT_TIMESTAMP)
@default(dbgenerated("…")) baza (ixtiyoriy ifoda) ha
@default("orta"), @default(false) baza ha
@default(uuid(7)), @default(cuid()) Prisma Client yo'q
@updatedAt Prisma Client yo'q

Biz buni tekshirdik: namuna model yozib, prisma migrate diff --from-empty --to-schema bilan Prisma qanday DDL yasashini chiqardik (biz ishga tushirdik, 7.10.1). Model:

ts
model Tolov {
  id         String      @id @default(uuid(7)) @db.Uuid
  raqam      BigInt      @unique
  summa      Decimal     @db.Decimal(12, 2)
  izoh       String?     @db.Text
  holat      TolovHolati @default(kutilmoqda)
  yaratildi  DateTime @default(now()) @map("yaratilgan_vaqt")
  yangilandi DateTime @updatedAt @map("yangilangan_vaqt")
  egasiId    BigInt      @map("egasi_id")
  tashqiId   String      @map("tashqi_id")

  @@unique([egasiId, tashqiId])
  @@index([egasiId, yaratildi(sort: Desc)])
  @@map("tolovlar")
}

Prisma yasagan SQL (qisqartirilgan):

sql
CREATE TYPE "tolov_holati" AS ENUM ('kutilmoqda', 'tolandi', 'bekor');

CREATE TABLE "tolovlar" (
  "id" UUID NOT NULL,
  "raqam" BIGINT NOT NULL,
  "summa" DECIMAL(12,2) NOT NULL,
  "izoh" TEXT,
  "holat" "tolov_holati" NOT NULL DEFAULT 'kutilmoqda',
  "yaratilgan_vaqt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
  "yangilangan_vaqt" TIMESTAMP(3) NOT NULL,
  "egasi_id" BIGINT NOT NULL,
  "tashqi_id" TEXT NOT NULL,
  CONSTRAINT "tolovlar_pkey" PRIMARY KEY ("id")
);
CREATE UNIQUE INDEX "tolovlar_raqam_key" ON "tolovlar"("raqam");
CREATE INDEX "tolovlar_egasi_id_yaratilgan_vaqt_idx"
  ON "tolovlar"("egasi_id", "yaratilgan_vaqt" DESC);
CREATE UNIQUE INDEX "tolovlar_egasi_id_tashqi_id_key"
  ON "tolovlar"("egasi_id", "tashqi_id");

Qarang: id UUID NOT NULL — DEFAULT yo'q. yangilangan_vaqt … NOT NULL — DEFAULT ham, trigger ham yo'q. Bu qiymatlarni Prisma Client JS'da o'zi hisoblab yuboradi.

Yana bir detal: vaqt maydonlariga @db.Timestamptz yozmadik — va Prisma TIMESTAMP(3) ni, ya'ni vaqt zonasisiz turni tanladi. Kanon esa har vaqt maydoniga @db.Timestamptz(6) qo'yadi. Mavjud bazada bu xato introspection'da ko'rinadi; yangi jadval yaratayotganda esa jim o'tib ketadi.

flowchart LR
  C["db.tolov.create()"] -->|"id = uuid v7, yangilangan_vaqt = hozir"| P[Prisma Client]
  P -->|INSERT: hamma qiymat bilan| DB[(PostgreSQL)]
  DB -->|"DEFAULT: holat, yaratilgan_vaqt"| DB
  R["psql / raw SQL"] -->|INSERT: id siz| DB

Diagrammada ikki yo'l: Prisma orqali yozganda client'dagi qiymatlar qo'shiladi. psql yoki raw SQL'da esa faqat bazadagi DEFAULT'lar ishlaydi — id va yangilangan_vaqt bo'sh qoladi.

4.2 Oqibati: Prisma'dan tashqari yozish

Prisma'dan tashqarida — psql, boshqa servis, qisman ko'chirish skripti — id siz yozsangiz, nima bo'ladi? O'sha jadvalni bazada yaratib sinaymiz:

sql
BEGIN;
CREATE TABLE tolovlar (
  id uuid NOT NULL PRIMARY KEY,
  raqam bigint NOT NULL,
  yangilangan_vaqt timestamptz(3) NOT NULL
);
INSERT INTO tolovlar (raqam) VALUES (1001);
ROLLBACK;

Natija:

text
BEGIN
CREATE TABLE
ERROR:  null value in column "id" of relation "tolovlar" violates not-null constraint
DETAIL:  Failing row contains (null, 1001, null).
ROLLBACK

"tolovlar jadvalining id ustunidagi null qiymat NOT NULL cheklovini buzadi". Bazaning o'zi id ni bilmaydi. Raw SQL'dan ham yoziladigan jadvalda id'ni baza bersin: PostgreSQL 18 da @default(dbgenerated("uuidv7()")) (PG 18 ning uuidv7() funksiyasi, Primary key tanlovi) yoki kanondagidek autoincrement().

4.3 Kanon nega @updatedAt ishlatmaydi

Kanon Vazifa modelida yangilanganVaqt va versiya ni bazadagi trigger yangilaydi (26-qism). Holat 20 bazasida tekshiramiz:

sql
SELECT column_name, column_default
FROM information_schema.columns
WHERE table_name = 'vazifalar'
  AND column_name IN ('id', 'versiya', 'tartib', 'yangilangan_vaqt')
ORDER BY column_name;

Natija:

text
   column_name    |             column_default
------------------+-----------------------------------------
 id               |
 tartib           |
 versiya          | 1
 yangilangan_vaqt | date_trunc('milliseconds'::text, now())
(4 rows)

id bo'sh ko'rinadi — u identity ustun (GENERATED ALWAYS AS IDENTITY), information_schema uni DEFAULT sifatida ko'rsatmaydi. tartib ni ham DEFAULT emas, trigger qo'yadi. Sxemada esa:

ts
/// trigger qo'yadi (010/013)
yangilanganVaqt DateTime @default(dbgenerated("date_trunc('milliseconds'::text, now())")) @map("yangilangan_vaqt") @db.Timestamptz(6)
/// trigger qo'yadi (013); bazada NOT NULL
tartib Int?

Nega trigger yaxshiroq: @updatedAt faqat Prisma orqali yangilanganda ishlaydi. pg ombori, psql yoki boshqa servisdan qilingan UPDATE vaqtni o'zgartirmaydi. Trigger esa kim yozsa ham ishlaydi — bizning loyihada ikki ombor (pg va Prisma) bir bazada.

tartib Int? — kanon qarori: bazada NOT NULL, lekin Prisma'da ixtiyoriy. Aks holda create() tartibni majburiy so'rardi, holbuki uni trigger qo'yadi.

Tekshirib ko'ring: @updatedAt bilan model, va ilovaning bir qismi Prisma'da, bir qismi $executeRaw bilan yangilaydi. Qaysi yozuvlarda vaqt eskirib qoladi?

Javob

$executeRaw (va umuman Prisma Client'ning model metodlaridan tashqari) bilan qilingan har UPDATE'da. @updatedAt — SQL'ga Prisma qo'shadigan qiymat; raw SQL'da uni hech kim qo'shmaydi. Bunday aralash loyihada vaqtni trigger bilan boshqarish ishonchliroq.

5. Decimal — pul uchun

5.1 Nega Float emas

Pul, miqdor va enum'larni modellash darsida pulni numeric da saqlashni o'rgandik. JS'ning number i esa ikkilik kasr:

js
console.log(0.1 + 0.2);            // 0.30000000000000004
console.log(35000.5 * 3);          // 105001.5
console.log((0.1 * 3).toFixed(20)); // 0.30000000000000004441

Prisma Decimal maydonini shuning uchun number emas, aniq o'nlik kasrli Decimal obyekti qilib qaytaradi.

5.2 Biz ishga tushirdik

Namuna Tolov modeli bilan (PostgreSQL 17.6, Prisma 7.10.1):

ts
const t = await db.tolov.create({
  data: {
    raqam: 1001n, summa: "35000.50",
    egasiId: 1n, tashqiId: "click-1",
  },
});
console.log("raqam:", typeof t.raqam, t.raqam);
console.log("summa:", t.summa.toString(), t.summa.toFixed(2));
console.log("uuid versiyasi:", t.id[14], "| holat:", t.holat);
console.log("updatedAt = createdAt:",
  t.yaratildi.getTime() === t.yangilandi.getTime());
try {
  JSON.stringify(t);
} catch (e) {
  console.log("JSON:", e.message);
}

Chiqish:

text
raqam: bigint 1001n
summa: 35000.5 35000.50
uuid versiyasi: 7 | holat: kutilmoqda
updatedAt = createdAt: true
JSON: Do not know how to serialize a BigInt

Kuzatuvlar:

  • summa ni satr ("35000.50") bilan berdik — aniqlik yo'qolmasin. toString() ortiqcha nolni tashlaydi, toFixed(2) — pul ko'rinishi.
  • UUID'ning 15-belgisi (id[14]) — versiya: 7. UUID v7 boshida vaqt bor, shuning uchun yangi yozuvlar tartib bilan o'sadi — indeks uchun v4 dan qulay (Primary key tanlovi). Qiymatning o'zi har safar boshqa.
  • @updatedAt yaratishda ham to'ldirildi — yaratildi bilan bir xil.
  • JSON.stringify yana bigint da yiqildi (raqam).

6. Noyoblik va indekslar

6.1 @unique, @@unique, @@index

Atribut Nima Bazada
@unique bitta maydon noyob CREATE UNIQUE INDEX …_key
@@unique([a, b]) juftlik noyob CREATE UNIQUE INDEX …_a_b_key
@@index([a, b]) oddiy indeks CREATE INDEX …_a_b_idx
@@id([a, b]) tarkibiy birlamchi kalit PRIMARY KEY (a, b)

Noyob maydonlar Prisma'ga boshqa imkoniyat ham beradi: findUnique faqat @id yoki @unique/@@unique bo'yicha qidiradi. Kanonda @@unique([id, egasiId]) bor — u tarkibiy tashqi kalit uchun (Prisma: relations).

Noyoblik buzilsa — xato kodi P2002. Biz namunada bir xil (egasiId, tashqiId) bilan ikkinchi to'lovni yozdik; e.meta (qisqartirilgan):

text
P2002 {"driverAdapterError":{"name":"DriverAdapterError","cause":{"originalCode":"23505", … "constraint":{"index":"tolovlar_egasi_id_tashqi_id_key"},"table":"tolovlar"}},"modelName":"Tolov"}

Postgres'ning asl kodi — 23505 (Foreign key va referential actions darsidagi xato kodlari). Prisma 7 da asl ma'lumot meta.driverAdapterError.cause ichida — kanon PrismaOmbori xatolarni aynan shu yerdan o'qib, 409 ga aylantiradi.

6.2 Indeks nomi va murakkab indekslar

Kanondagi Vazifa indekslari:

ts
@@index([egasiId], map: "vazifalar_egasi_id_idx")
@@index([otaId], map: "vazifalar_ota_id_idx", where: raw("(ota_id IS NOT NULL)"))
@@index([egasiId, yaratilganVaqt(sort: Desc), id(sort: Desc)], map: "vazifalar_royxat_idx", where: raw("(ochirilgan_vaqt IS NULL)"))
  • map: — bazadagi aniq nom. Usiz Prisma o'z nomini kutadi va migratsiyada "eski indeksni o'chirib, yangisini yarat" deb o'ylaydi.
  • sort: Desc — indeksdagi tartib (Qaysi ustunga va qanday tartibda indeks).
  • where: raw(…) — partial indeks (Partial, expression va covering indekslar); buning uchun generator'da previewFeatures = ["partialIndexes"].
  • Foydalanuvchi modelidagi @@index([sozlamalar(ops: JsonbPathOps)], type: Gin, …) — GIN indeks va operator klassi.

Ifoda indekslari (lower(email), trigram) esa Prisma sxemasida ifodalanmaydi — db pull ogohlantirgan edi. Ular bazada qoladi, Prisma ularni bilmaydi.

7. Enum, Json va qo'llanmaydigan turlar

Enum:

ts
enum Ustuvorlik {
  past
  orta
  yuqori

  @@map("ustuvorlik")
}

JS'da enum — satr birlashmasi ("past" | "orta" | "yuqori"), generatsiya qilingan Ustuvorlik obyekti ham bor. Qiymatlar tartibi bazadagi bilan bir xil (past < orta < yuqori — Pul, miqdor va enum'larni modellash).

Json — sozlamalar Json @default("{}"): JS'da tayyor obyekt, lekin turi umumiy (JsonValue) — ichidagi til ning turini Prisma bilmaydi. Bazadagi CHECK (til ∈ …, JSONB) haqiqiy himoya bo'lib qoladi.

Unsupported — qidiruv Unsupported("tsvector")?: Prisma bu turni bilmaydi, maydon client'da umuman yo'q. Qidiruv kerak bo'lsa — raw SQL (Prisma: raw SQL va TypedSQL).

8. Ko'p uchraydigan xatolar

Belgi Sabab Davosi
Do not know how to serialize a BigInt BigInt maydon JSON.stringify da chegarada Number() (tekshiruv bilan) yoki String()
jadval topilmadi / migratsiya yangi jadval yaratmoqchi @@map yo'q modelga @@map("jadval")
raw SQL INSERT'da id null uuid(7) client'da dbgenerated("uuidv7()") yoki autoincrement()
yangilangan_vaqt o'zgarmaydi @updatedAt + raw SQL trigger
create() trigger qo'yadigan maydonni so'raydi maydon majburiy sxemada ixtiyoriy (Int?)
pul hisobida 0.30000000000000004 Float Decimal @db.Decimal(p, s)

9. Mashqlar

Mashqlar kurs/mashqlar/27/21-prisma-modellar/ da. 2- va 3-mashq Node 24 da tekshirilgan (biz ishga tushirdik).

1-mashq (oson): atributni tanlang

  • Bazadagi ustun nomi muallif_id, kodda muallifId — @("muallif_id")
  • Model Izoh, jadval izohlar — @@("izohlar")
  • Ikki maydon juftligi noyob — @@([vazifaId, tegId])
  • Vaqt zonali vaqt — @db.(6)
  • Qiymatni client qo'yadigan "yangilangan vaqt" — @
Yechim
  • map / @@map — maydon va model nomlari xaritasi.
  • unique — kanonda VazifaTegi uchun esa @@id([vazifaId, tegId]): juftlik birlamchi kalitning o'zi.
  • Timestamptz — sukut timestamp(3) vaqt zonasisiz.
  • updatedAt — faqat Prisma orqali yozilganda ishlaydi.

2-mashq (o'rta): bigint ni JSON'ga

API javobi uchun jsongaXavfsiz(qiymat) funksiyasini yozing: JSON.stringify ning ikkinchi argumenti (replacer) bilan har bigint ni xavfsiz bo'lsa number, katta bo'lsa satr qilsin. Kanon misolidagi obyekt va 2⁵³ + 1 bilan tekshiring.

Ishora: replacer (kalit, qiymat) => … har qiymat uchun chaqiriladi; typeof q === "bigint"; xavfsizlik — Number.isSafeInteger(Number(q)) (JSON chuqur: replacer, reviver va chegaralar).

Yechim
js
function jsongaXavfsiz(qiymat) {
  return JSON.stringify(qiymat, (_kalit, q) => {
    if (typeof q !== "bigint") return q;
    const n = Number(q);
    return Number.isSafeInteger(n) ? n : q.toString();
  });
}

const vazifa = {
  id: 1n, matn: "Kitob o'qish", ustuvorlik: "yuqori",
  egasiId: 1n, katta: 9007199254740993n,
};
console.log(jsongaXavfsiz(vazifa));

Konsolda:

text
{"id":1,"matn":"Kitob o'qish","ustuvorlik":"yuqori","egasiId":1,"katta":"9007199254740993"}

Katta son satr bo'ldi — aniqlik yo'qolmadi, lekin mijoz uni son deb kutsa, shartnomada aytilishi kerak. Kanon API'da id'lar baribir kichik va number — son() tekshiruvi esa "katta bo'lsa xato" yo'lini tanlagan.

3-mashq (qiyin): @map qatorlarini yasash

db pull natijasini qo'lda tartiblash zerikarli. maydonQatori(ustun, tur) funksiyasini yozing: ustun nomini camelCase ga o'tkazsin va nom o'zgargan bo'lsa @map("…") qo'shsin. Ustunlar: id, egasi_id, yaratilgan_vaqt, matn, izohlar_soni.

Ishora: /_([a-z])/g va replace ning funksiya argumenti (RegExp asoslari va metodlari).

Yechim
js
function camel(ustun) {
  return ustun.replace(/_([a-z])/g, (_m, h) => h.toUpperCase());
}

function maydonQatori(ustun, tur) {
  const nom = camel(ustun);
  const map = nom === ustun ? "" : ` @map("${ustun}")`;
  return `${nom.padEnd(15)} ${tur}${map}`.trimEnd();
}

const ustunlar = [
  ["id", "BigInt"], ["egasi_id", "BigInt"],
  ["yaratilgan_vaqt", "DateTime"], ["matn", "String"],
  ["izohlar_soni", "Int"],
];
for (const [u, t] of ustunlar) console.log(maydonQatori(u, t));

Konsolda:

text
id              BigInt
egasiId         BigInt @map("egasi_id")
yaratilganVaqt  DateTime @map("yaratilgan_vaqt")
matn            String
izohlarSoni     Int @map("izohlar_soni")

padEnd(15) — ustunlarni tekislash (Prisma formatlovchisi prisma format buni o'zi qiladi). Haqiqiy loyihada @id, @default va @db.* ni db pull natijasidan saqlab qolish kerak — bu funksiya faqat nomlarni o'giradi.

10. Loyiha qadami: holat 20 — modellarni tartiblash

Holat 20 ning ikkinchi qadami. Hali commit qilmang — commit PrismaOmbori tayyor bo'lgach.

db pull natijasini kanon qoidalariga keltiring:

  1. Modellar: foydalanuvchilar → Foydalanuvchi, vazifalar → Vazifa, teglar → Teg, vazifa_teglari → VazifaTegi, izohlar → Izoh, vazifa_tarixi → VazifaTarixi; har biriga @@map.
  2. Maydonlar camelCase, har o'zgargan nomga @map.
  3. Vaqt ustunlari — @db.Timestamptz(6), Vazifa.yaratilganVaqt va yangilanganVaqt — dbgenerated("date_trunc('milliseconds'::text, now())") (bazadagi DEFAULT aynan shu).
  4. tartib Int? — izoh bilan (trigger qo'yadi).
  5. qidiruv Unsupported("tsvector")? — @default siz.
  6. Har @@index va @@unique ga map: — bazadagi nom.
  7. /// izohlar: qaysi maydonni trigger boshqaradi, qaysi CHECK bazada.
  8. Fayl boshida izoh: "SXEMA MANBAI — SQL migratsiyalar; bu fayl Prisma Client uchun".

Tekshiruv: npx prisma validate — The schema at prisma\schema.prisma is valid; npm run db:generate; npm run tip. Kanondagi to'liq Vazifa va Foydalanuvchi modellari — relation maydonlari bilan birga keyingi darsda.

11. Real ishda

  • Mavjud bazaga Prisma ulashda eng ko'p vaqt aynan @map/@@map va indeks nomlariga ketadi — buni bir marta to'g'ri qilish migratsiyadagi kutilmagan DROP INDEX lardan saqlaydi.
  • BigInt va Decimal ni JSON'ga aylantirish — Prisma loyihalaridagi klassik muammo; ko'p jamoalar bitta umumiy serializer yozadi.
  • Intervyuda: "@default(uuid()) bazada DEFAULT yaratadimi?", "@updatedAt qachon ishlamaydi?", "Pulni Prisma'da qanday saqlaysiz?"

Xulosa

  • Model — jadval, maydon — ustun; @map/@@map kod va baza nomlarini ajratadi, baza o'zgarmaydi.
  • @ — maydon, @@ — model atributi; @db.* — aniq Postgres turi.
  • autoincrement(), now(), dbgenerated() — bazada; uuid(7), cuid(), @updatedAt — Prisma Client'da (raw SQL ularni bilmaydi).
  • BigInt → JS bigint (JSON'ga o'zi o'tmaydi), Decimal → aniq kasr obyekti, enum → satr.
  • Indekslarga map:; partial — where: raw(); ifoda indeksi va tsvector — Prisma'da yo'q.

Keyingi dars: Prisma: relations — @relation, 1:N, N:M, self-relation (kichik vazifalar), tarkibiy tashqi kalit va onDelete.

Manbalar

Ulashish:Telegram'da

Izohlar (0)

Izoh yozish uchun kiring.

  • Hozircha izoh yo'q. Birinchi bo'ling!
Prisma modellar va atributlar: @id, @default, @map, @@index, BigInt, Decimal va enum — IlmHamroh