Xây dựng Công cụ Quản lý Dự án với Prisma
Tôi đang xây dựng một công cụ quản lý dự án cộng tác giống như Trello.
Tôi đang sử dụng React, Express.js, PostgreSQL và Socket.io. Trước khi viết bất kỳ route backend nào, tôi phải thiết kế schema cơ sở dữ liệu.
Schema chính là nền tảng. Nếu schema sai, toàn bộ ứng dụng sẽ thất bại. Dưới đây là phân tích chi tiết về thiết kế schema Prisma của tôi.
Các Model
• User: Lưu trữ tên, email và mật khẩu. Tôi sử dụng cuid() cho các ID. Điều này tạo ra các chuỗi dài và duy nhất. Nó tốt hơn số vì không làm lộ số lượng người dùng của bạn trên URL.
• Project: Chứa tên và mô tả dự án. Tôi đã để phần mô tả là tùy chọn bằng cách sử dụng dấu chấm hỏi.
• ProjectMember: Đây là một bảng trung gian (junction table). Nó liên kết User với Project. Vì một người dùng có thể tham gia nhiều dự án và một dự án có nhiều người dùng, bạn cần bảng trung gian này để quản lý mối quan hệ nhiều-nhiều (many-to-many). Tôi đã thêm một ràng buộc duy nhất (unique constraint) để ngăn cùng một người dùng tham gia vào một dự án hai lần.
• Board: Các Task nằm trong các Board. Các Board nằm trong các Project. Cấu trúc phân cấp này giúp việc kéo-thả trở nên dễ dàng. Việc di chuyển một task giữa các cột chỉ đơn giản là cập nhật một trường duy nhất.
• Task: Đây là model cốt lõi. Nó có hai mối quan hệ khác nhau với model User:
- Một người dùng được giao (tùy chọn).
- Một người tạo (bắt buộc). Tôi phải đặt tên rõ ràng cho các mối quan hệ này để Prisma biết đâu là đâu.
• Comment: Người dùng có thể để lại bình luận trên các task. Tôi đã đặt tên mối quan hệ là "author" thay vì "user" để mã nguồn dễ đọc hơn.
• Notification: Một model đơn giản để theo dõi tin nhắn cho người dùng.
Các bài học kỹ thuật rút ra
Tôi đã gặp phải một vài lỗi trong quá trình xây dựng dự án này. Hãy lưu ý những điều sau:
- Tên mối quan hệ (Relation Names): Nếu hai trường cùng trỏ đến một model, bạn phải đặt tên cho các mối quan hệ. Nếu không, Prisma sẽ báo lỗi.
- Các trường có thể null (Nullable Fields): Nếu một mối quan hệ là tùy chọn, bạn phải đặt dấu chấm hỏi ở cả trường quan hệ và trường khóa ngoại (foreign key).
- Lỗi cú pháp (Syntax Errors): Prisma yêu cầu sử dụng dấu ngoặc kép cho các giá trị mặc định kiểu chuỗi. Sử dụng dấu ngoặc đơn sẽ bị lỗi.
- Cú pháp quan hệ (Relation Syntax): Luôn sử dụng đúng cú pháp:
@relation(fields: [localField], references: [remoteField]).
Schema hiện đã được migrate. Tiếp theo, tôi sẽ xây dựng backend Express và thiết lập Socket.io để cập nhật thời gian thực.
Xây dựng một công cụ quản lý dự án từ con số 0, bắt đầu với Prisma schema
Xây dựng một công cụ quản lý dự án là một cách tuyệt vời để học về thiết kế cơ sở dữ liệu, các mối quan hệ và cách cấu trúc lớp dữ liệu của một ứng dụng. Trong bài viết này, chúng ta sẽ đi sâu vào bước đầu tiên và quan trọng nhất: thiết kế Prisma schema.
Tầm quan trọng của việc thiết kế Schema
Schema là bản thiết kế cho cơ sở dữ liệu của bạn. Một schema được thiết kế tốt sẽ giúp đảm bảo tính toàn vẹn của dữ liệu, tối ưu hóa các truy vấn và giúp việc mở rộng ứng dụng trở nên dễ dàng hơn trong tương lai. Nếu schema của bạn lộn xộn, việc phát triển các tính năng mới sẽ trở thành một cơn ác mộng.
Tại sao lại là Prisma?
Prisma là một ORM (Object-Relational Mapping) thế hệ mới giúp việc truy cập cơ sở dữ liệu trở nên dễ dàng và đảm bảo an toàn về kiểu dữ liệu (type-safe). Nó cho phép bạn định nghĩa mô hình dữ liệu của mình trong một tệp duy nhất, dễ đọc và tự động tạo ra một client an toàn về kiểu cho ứng dụng của bạn.
Bước 1: Định nghĩa User Model
Mọi công cụ quản lý dự án đều cần người dùng. Một người dùng có thể tạo các dự án, được giao các công việc và quản lý hồ sơ cá nhân của chính họ.
model User {
id String @id @default(cuid())
email String @unique
name String?
projects Project[]
tasks Task[]
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
}
Trong model User này:
id: Sử dụngcuid()để tạo một định danh duy nhất.email: Được đánh dấu là@uniqueđể đảm bảo không có hai người dùng nào có cùng email.projectsvàtasks: Đây là các mối quan hệ (relations) cho phép một người dùng có nhiều dự án và nhiều công việc.
Bước 2: Định nghĩa Project Model
Một dự án là một tập hợp các công việc và thuộc về một người dùng (chủ sở hữu).
model Project {
id String @id @default(cuid())
title String
description String?
ownerId String
owner User @relation(fields: [ownerId], references: [id])
tasks Task[]
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
}
Trong model Project này:
ownerId: Lưu trữ ID của người dùng sở hữu dự án.owner: Thiết lập mối quan hệ giữaProjectvàUserthông quaownerId.tasks: Một dự án có thể chứa nhiều công việc.
Bước 3: Định nghĩa Task Model
Công việc (Task) là cốt lõi của ứng dụng. Chúng thuộc về một dự án và có thể được giao cho một người dùng cụ thể.
model Task {
id String @id @default(cuid())
title String
description String?
status Status @default(TODO)
priority Priority @default(MEDIUM)
projectId String
project Project @relation(fields: [projectId], references: [id])
assigneeId String?
assignee User? @relation(