กลับไปหน้าหลัก

บทที่ 2: การออกแบบ Prisma Schema

ศึกษาการออกแบบฐานข้อมูลด้วย Prisma Schema Language แบบมืออาชีพ! 🏗️
45 นาที
ระดับกลาง
Hands-on
🧠 ทำไมต้องออกแบบ Schema ให้ดี?

• 🏗️ Foundation ที่แข็งแรง: Schema ที่ดีเป็นรากฐานของแอปพลิเคชันที่ยืนยาว

• ⚡ Performance: Index และ relation ที่ถูกต้องทำให้ query เร็วขึ้น

• 🔒 Data Integrity: Constraints และ validation ป้องกันข้อมูลผิดพลาด

• 🚀 Scalability: Schema ที่ยืดหยุ่นรองรับการเติบโตในอนาคต

📊 ประเภทของ Fields ใน Prisma

String Types
String

ข้อความทั่วไป

name String

String?

ข้อความที่อาจเป็น null

nickname String?

String @unique

ข้อความที่ไม่ซ้ำ

email String @unique

Number Types
Int

จำนวนเต็ม

age Int

Float

จำนวนทศนิยม

price Float

BigInt

จำนวนเต็มขนาดใหญ่

views BigInt

Date & Boolean
DateTime

วันที่และเวลา

createdAt DateTime @default(now())

Boolean

true หรือ false

isPublished Boolean @default(false)

Special Types
Json

ข้อมูล JSON

metadata Json?

Bytes

ข้อมูล binary

avatar Bytes?

🛠️ ขั้นตอนการออกแบบ Schema

วางแผนและวิเคราะห์ข้อมูล (Data Planning)

วิเคราะห์ business requirements และออกแบบโครงสร้างข้อมูลก่อนเขียนโค้ด - ขั้นตอนสำคัญที่จะกำหนดความสำเร็จของโปรเจค

📋 ขั้นตอนย่อย:
  • ระบุ entities หลัก (Users, Posts, Categories)

  • กำหนด attributes ของแต่ละ entity

  • วิเคราะห์ relationships ระหว่าง entities

  • วางแผน data validation และ constraints

💻 ตัวอย่างโค้ด:
// ตัวอย่างการวางแผน - ระบบบล็อก
/*
Business Requirements:
- ผู้ใช้สามารถสร้างบัญชีและล็อกอิน
- ผู้ใช้เขียนโพสต์ได้หลายโพสต์
- โพสต์สามารถมีหลายแท็ก
- ผู้ใช้คอมเมนต์โพสต์ได้
- ผู้ใช้มีโปรไฟล์ส่วนตัว

Entity Analysis:
1. User (ผู้ใช้)
   - id, email, name, password
   - has one Profile
   - has many Posts
   - has many Comments

2. Profile (โปรไฟล์)
   - id, bio, avatar, userId
   - belongs to one User

3. Post (โพสต์)
   - id, title, content, authorId
   - belongs to one User (author)
   - has many Comments
   - has many Tags (many-to-many)

4. Comment (คอมเมนต์)
   - id, content, postId, authorId
   - belongs to one Post
   - belongs to one User (author)

5. Tag (แท็ก)
   - id, name, color
   - belongs to many Posts
*/
💡 เทคนิคและคำแนะนำ:
🎯 เริ่มจาก core entities ก่อน แล้วค่อยเพิ่ม features
📝 เขียน user stories เพื่อเข้าใจ business logic
🔗 ระบุ relationships อย่างละเอียด
⚡ คิดถึง performance ตั้งแต่ขั้นวางแผน
สร้าง Database Schema (Schema Definition)
กำหนด Relations และ Constraints
Generate Client และ Testing
Optimization และ Advanced Features
ขั้นตอนสุดท้าย

🔗 ประเภทของ Relations

📝
One-to-Many (1:M)

ผู้ใช้หนึ่งคนมีหลายโพสต์

💻 ตัวอย่างโค้ด:
model User {
  id    Int    @id @default(autoincrement())
  name  String
  posts Post[]
}

model Post {
  id       Int  @id @default(autoincrement())
  title    String
  authorId Int
  author   User @relation(fields: [authorId], references: [id])
}
🏷️
Many-to-Many (M:M)

โพสต์หนึ่งโพสต์มีหลาย tags, tag หนึ่งตัวอยู่ในหลายโพสต์

💻 ตัวอย่างโค้ด:
model Post {
  id   Int    @id @default(autoincrement())
  title String
  tags  Tag[]
}

model Tag {
  id    Int    @id @default(autoincrement())
  name  String @unique
  posts Post[]
}
👤
One-to-One (1:1)

ผู้ใช้หนึ่งคนมีโปรไฟล์เพียงหนึ่งโปรไฟล์

💻 ตัวอย่างโค้ด:
model User {
  id      Int      @id @default(autoincrement())
  email   String   @unique
  profile Profile?
}

model Profile {
  id     Int    @id @default(autoincrement())
  bio    String?
  userId Int    @unique
  user   User   @relation(fields: [userId], references: [id])
}

⭐ Best Practices

📝 การตั้งชื่อ Models และ Fields

ใช้ PascalCase สำหรับ Models และ camelCase สำหรับ fields

ตัวอย่าง:
Model: User, BlogPost, ProductCategory
Fields: firstName, createdAt, isPublished
Relations: posts, author, comments
🔑 Primary Keys และ IDs

ใช้ @id และ @default(autoincrement()) สำหรับ primary key

ตัวอย่าง:
id Int @id @default(autoincrement())
uuid String @id @default(uuid())
รวม composite key: @@id([userId, postId])
📅 Timestamps

เพิ่ม createdAt และ updatedAt ให้ทุก Model

ตัวอย่าง:
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
publishedAt DateTime? // อาจเป็น null
🔍 Indexes และ Performance

เพิ่ม index สำหรับ fields ที่ใช้ query บ่อย

ตัวอย่าง:
@@index([email]) // single field
@@index([userId, status]) // composite
@@unique([slug]) // unique constraint

💻 ตัวอย่าง Schema ตามสถานการณ์จริง

Schema สำหรับระบบบล็อก

Schema ที่ครอบคลุม Users, Posts, Comments, Tags และ Profiles พร้อม relations ทั้งหมด

// prisma/schema.prisma - Schema สำหรับระบบบล็อกง่ายๆ
generator client {
  provider = "prisma-client-js"
}

datasource db {
  provider = "postgresql" // หรือ mysql, sqlite
  url      = env("DATABASE_URL")
}

// Model สำหรับผู้ใช้
model User {
  id        Int      @id @default(autoincrement())
  email     String   @unique
  name      String
  role      Role     @default(USER)
  profile   Profile?
  posts     Post[]
  comments  Comment[]
  createdAt DateTime @default(now())
  updatedAt DateTime @updatedAt

  @@map("users") // ชื่อ table ในฐานข้อมูล
}

// Model สำหรับโปรไฟล์ผู้ใช้
model Profile {
  id     Int     @id @default(autoincrement())
  bio    String?
  avatar String?
  userId Int     @unique
  user   User    @relation(fields: [userId], references: [id], onDelete: Cascade)

  @@map("profiles")
}

// Model สำหรับโพสต์
model Post {
  id          Int       @id @default(autoincrement())
  title       String
  content     String?
  slug        String    @unique
  published   Boolean   @default(false)
  publishedAt DateTime?
  authorId    Int
  author      User      @relation(fields: [authorId], references: [id])
  comments    Comment[]
  tags        Tag[]
  views       Int       @default(0)
  createdAt   DateTime  @default(now())
  updatedAt   DateTime  @updatedAt

  @@map("posts")
  @@index([authorId])
  @@index([published])
}

// Model สำหรับคอมเมนต์
model Comment {
  id        Int      @id @default(autoincrement())
  content   String
  postId    Int
  post      Post     @relation(fields: [postId], references: [id], onDelete: Cascade)
  authorId  Int
  author    User     @relation(fields: [authorId], references: [id])
  createdAt DateTime @default(now())

  @@map("comments")
  @@index([postId])
  @@index([authorId])
}

// Model สำหรับแท็ก
model Tag {
  id    Int    @id @default(autoincrement())
  name  String @unique
  color String @default("#3B82F6")
  posts Post[]

  @@map("tags")
}

// Enum สำหรับบทบาทผู้ใช้
enum Role {
  USER
  ADMIN
  MODERATOR
}

📋 อ้างอิงเร็ว: Attributes ที่ใช้บ่อย

Attributeการใช้งานตัวอย่าง
@idกำหนด Primary Keyid Int @id @default(autoincrement())
@uniqueกำหนดให้ค่าไม่ซ้ำemail String @unique
@default()กำหนดค่าเริ่มต้นcreatedAt DateTime @default(now())
@relationกำหนด Foreign Keyauthor User @relation(fields: [authorId], references: [id])
@@indexสร้าง Database Index@@index([email, status])
@@mapกำหนดชื่อ Table@@map("users")