Mundarija (29)
- Bu darsda
- 1. Nega bu kerak?
- 2. Model va maydon
- 2.1 Tuzilishi
- 2.2 Nomlash qoidasi (kanon)
- 3. Skalyar turlar va JS
- 3.1 Moslik jadvali
- 3.2 Kanon tajribasi: turlar JS'da
- 3.3 BigInt bilan yashash
- 4. @default: kim qiymat beradi
- 4.1 Bazada yoki client'da
- 4.2 Oqibati: Prisma'dan tashqari yozish
- 4.3 Kanon nega @updatedAt ishlatmaydi
- 5. Decimal — pul uchun
- 5.1 Nega Float emas
- 5.2 Biz ishga tushirdik
- 6. Noyoblik va indekslar
- 6.1 @unique, @@unique, @@index
- 6.2 Indeks nomi va murakkab indekslar
- 7. Enum, Json va qo'llanmaydigan turlar
- 8. Ko'p uchraydigan xatolar
- 9. Mashqlar
- 1-mashq (oson): atributni tanlang
- 2-mashq (o'rta): bigint ni JSON'ga
- 3-mashq (qiyin): @map qatorlarini yasash
- 10. Loyiha qadami: holat 20 — modellarni tartiblash
- 11. Real ishda
- Xulosa
- Manbalar
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@updatedAtqiymatni Prisma Client qo'yadi, bazada DEFAULT bo'lmaydi;now()vaautoincrement()esa bazaning o'zida.BigIntJS'dabigint,Decimal— maxsus obyekt: ikkalasi hamJSON.stringifyva arifmetikada ehtiyot talab qiladi.
Bu darsda
db pullnatijasini Prisma uslubiga keltirasiz: modelVazifa, maydonegasiId, bazada nomlar o'zgarmaydi.- Maydon va model atributlarini o'qiysiz va qaysi biri bazada, qaysi biri client'da ishlashini bilasiz.
BigInt,Decimal,DateTime,Jsonva 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:
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:
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())— maydonid, turiBigInt, u birlamchi kalit va qiymatini baza beradi.egasiId BigInt @map("egasi_id")— koddaegasiId, bazadaegasi_id.///— hujjat izohi: generatsiya qilingan TypeScript'da maydon ustida ko'rinadi (muharrir maslahatida). Oddiy//izohi esa faqat sxemada qoladi.egasivavazifaTeglari— 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
Vazifamodelidan@@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:
bigint 1 true yuqori {"til":"uz-Latn","mavzu":"qorongi","bildirishnoma":{"email":true,"telegram":true}}
JSON.stringify(bigint): Do not know how to serialize a BigIntQatorma-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):
SQL: SELECT … "public"."vazifalar"."ustuvorlik"::text, … WHERE "public"."vazifalar"."id" = $1Enum ustuni ::text bilan o'qiladi — Prisma enum'ni satr sifatida oladi va o'zi tekshiradi.
3.3 BigInt bilan yashash
Ikki yo'l bor:
- Chegarada aylantirish — API javobidan oldin
Number(v.id). Xavfsiz, agar qiymatNumber.MAX_SAFE_INTEGER(2⁵³ − 1) dan kichik bo'lsa. KanonPrismaOmborishunday qiladi:son()yordamchisi tekshiradi va katta bo'lsa xato beradi. - Sxemada
Int— agar jadval hech qachon 2 milliarddan oshmasa. Lekin bazadagi turbigintbo'lsa, Prisma uniBigIntdeb introspection qiladi — turni faqat sxemada o'zgartirib bo'lmaydi.
Kichik namuna — brauzerda ishlaydi:
const id = 9007199254740993n; // 2^53 + 1
console.log(Number(id)); // 9007199254740992
console.log(Number.isSafeInteger(Number(id))); // false
console.log(Number(48n) + 1); // 49Birinchi 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:
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):
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| DBDiagrammada 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:
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:
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:
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:
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:
/// 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:
@updatedAtbilan model, va ilovaning bir qismi Prisma'da, bir qismi$executeRawbilan 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:
console.log(0.1 + 0.2); // 0.30000000000000004
console.log(35000.5 * 3); // 105001.5
console.log((0.1 * 3).toFixed(20)); // 0.30000000000000004441Prisma 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):
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:
raqam: bigint 1001n
summa: 35000.5 35000.50
uuid versiyasi: 7 | holat: kutilmoqda
updatedAt = createdAt: true
JSON: Do not know how to serialize a BigIntKuzatuvlar:
summani 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. @updatedAtyaratishda ham to'ldirildi —yaratildibilan bir xil.JSON.stringifyyanabigintda 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):
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:
@@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'dapreviewFeatures = ["partialIndexes"].Foydalanuvchimodelidagi@@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:
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, koddamuallifId—@("muallif_id") - Model
Izoh, jadvalizohlar—@@("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
VazifaTegiuchun 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
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:
{"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
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:
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:
- Modellar:
foydalanuvchilar→Foydalanuvchi,vazifalar→Vazifa,teglar→Teg,vazifa_teglari→VazifaTegi,izohlar→Izoh,vazifa_tarixi→VazifaTarixi; har biriga@@map. - Maydonlar camelCase, har o'zgargan nomga
@map. - Vaqt ustunlari —
@db.Timestamptz(6),Vazifa.yaratilganVaqtvayangilanganVaqt—dbgenerated("date_trunc('milliseconds'::text, now())")(bazadagi DEFAULT aynan shu). tartib Int?— izoh bilan (trigger qo'yadi).qidiruv Unsupported("tsvector")?—@defaultsiz.- Har
@@indexva@@uniquegamap:— bazadagi nom. ///izohlar: qaysi maydonni trigger boshqaradi, qaysi CHECK bazada.- 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/@@mapva indeks nomlariga ketadi — buni bir marta to'g'ri qilish migratsiyadagi kutilmaganDROP INDEXlardan saqlaydi. BigIntvaDecimalni JSON'ga aylantirish — Prisma loyihalaridagi klassik muammo; ko'p jamoalar bitta umumiy serializer yozadi.- Intervyuda: "
@default(uuid())bazada DEFAULT yaratadimi?", "@updatedAtqachon ishlamaydi?", "Pulni Prisma'da qanday saqlaysiz?"
Xulosa
- Model — jadval, maydon — ustun;
@map/@@mapkod 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→ JSbigint(JSON'ga o'zi o'tmaydi),Decimal→ aniq kasr obyekti, enum → satr.- Indekslarga
map:; partial —where: raw(); ifoda indeksi vatsvector— Prisma'da yo'q.
Keyingi dars: Prisma: relations — @relation, 1:N, N:M, self-relation (kichik vazifalar), tarkibiy tashqi kalit va onDelete.
Manbalar
- Prisma schema reference (atributlar,
@defaultfunksiyalari,@updatedAt,@db.*): https://www.prisma.io/docs/orm/v7/reference/prisma-schema-reference - Models (
@map,@@map, enum, Unsupported): https://www.prisma.io/docs/orm/v7/prisma-schema/data-model/models - Indexes (
map,sort,type: Gin, partial): https://www.prisma.io/docs/orm/v7/prisma-schema/data-model/indexes - Working with BigInt, Decimal, Json fields: https://www.prisma.io/docs/orm/v7/prisma-client/special-fields-and-types
- Error reference (
P2002): https://www.prisma.io/docs/orm/v7/reference/error-reference - O'qilgan sana — 2026-10-27. Kanon o'lchovi (IlmHamroh, 2026-10): holat 20
schema.prisma, turlar, BigInt xatosi,::text. Biz ishga tushirdik (Prisma 7.10.1, PostgreSQL 17.6, Node 24.21.0):Tolovnamuna modeli —migrate diffDDL,create,Decimal, UUID v7,@updatedAt,P2002; holat 20 bazasidagi DEFAULT'lar; JS misollar va 2–3-mashqlar.
Izohlar (0)
Izoh yozish uchun kiring.
- Hozircha izoh yo'q. Birinchi bo'ling!