Prisma là một ORM mã nguồn mở dành cho Node.js và TypeScript. Nó bao gồm ba công cụ chính:
- Prisma Client: Trình xây dựng truy vấn được tự động tạo và an toàn theo kiểu dữ liệu.
- Prisma Migrate: Hệ thống thiết kế và di trú dữ liệu mạnh mẽ.
- Prisma Studio: Giao diện đồ họa (GUI) để xem và chỉnh sửa dữ liệu trong cơ sở dữ liệu.
Những công cụ này nhằm nâng cao hiệu suất làm việc với cơ sở dữ liệu cho các lập trình viên ứng dụng. Một trong những lợi ích lớn nhất của Prisma là mức độ trừu tượng mà nó cung cấp: thay vì phải viết các truy vấn SQL phức tạp hoặc tự xử lý các di trú của lược đồ, lập trình viên có thể làm việc với dữ liệu một cách trực quan hơn.
Trong hướng dẫn này, bạn sẽ xây dựng một REST API cho một ứng dụng blog nhỏ bằng TypeScript, sử dụng Prisma và cơ sở dữ liệu PostgreSQL. Bạn sẽ cài đặt cơ sở dữ liệu PostgreSQL cục bộ bằng Docker và triển khai các tuyến REST API bằng Express. Sau khi hoàn thành, bạn sẽ có một máy chủ web chạy trên máy của bạn, có thể phản hồi các yêu cầu HTTP và thao tác đọc/ghi dữ liệu vào cơ sở dữ liệu.
Yêu cầu trước khi bắt đầu
Hướng dẫn này giả định rằng bạn đã có:
- Node.js phiên bản 14 trở lên được cài đặt trên máy.
- Docker đã được cài đặt (để chạy cơ sở dữ liệu PostgreSQL). Có thể cài Docker trên macOS hoặc Windows từ trang chính thức của Docker.
- Biết cơ bản về TypeScript và REST APIs sẽ có ích nhưng không bắt buộc để theo dõi hướng dẫn này.
Bước 1: Tạo dự án TypeScript
Trong bước này, bạn sẽ thiết lập một dự án TypeScript đơn giản bằng npm
. Đây sẽ là nền tảng cho REST API mà bạn sẽ xây dựng.
Đầu tiên, hãy tạo một thư mục mới cho dự án của bạn:
$ mkdir my-blog
Tiếp theo, hãy điều hướng vào thư mục vừa tạo và khởi tạo một dự án npm rỗng. Lưu ý rằng tùy chọn -y
ở đây có nghĩa là bạn sẽ bỏ qua các câu hỏi tương tác của lệnh. Nếu muốn thực hiện từng bước thủ công, hãy bỏ -y
khỏi lệnh:
$ cd my-blog
$ npm init -y
Bạn sẽ nhận được đầu ra tương tự như sau với các giá trị mặc định đã được thiết lập:
Output
Wrote to /.../my-blog/package.json:
{
"name": "my-blog",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \\"Error: no test specified\\" && exit 1"
},
"keywords": [],
"author": "",
"license": "ISC"
}
Lệnh này sẽ tạo một tệp package.json
tối giản mà bạn sẽ sử dụng như một tệp cấu hình cho dự án npm
của mình. Bây giờ bạn đã sẵn sàng để cấu hình TypeScript cho dự án.
Chạy lệnh sau để thiết lập TypeScript cơ bản:
$ npm install typescript ts-node @types/node --save-dev
Lệnh này sẽ cài đặt ba gói như các phụ thuộc dành cho môi trường phát triển trong dự án của bạn:
typescript
: Bộ công cụ TypeScript.ts-node
: Gói cho phép chạy ứng dụng TypeScript mà không cần biên dịch trước sang JavaScript.@types/node
: Các định nghĩa kiểu TypeScript dành cho Node.js.
Việc cuối cùng cần làm là thêm tệp tsconfig.json
để đảm bảo TypeScript được cấu hình đúng cho ứng dụng bạn sắp xây dựng.
Trước tiên, hãy chạy lệnh sau để tạo tệp cấu hình này:
$ nano tsconfig.json
Thêm đoạn mã JSON sau vào tệp:
{
"compilerOptions": {
"sourceMap": true,
"outDir": "dist",
"strict": true,
"lib": ["esnext"],
"esModuleInterop": true
}
}
Lưu và thoát khỏi tệp.
Cấu hình này là thiết lập tiêu chuẩn và tối giản cho một dự án TypeScript. Nếu bạn muốn tìm hiểu thêm về từng thuộc tính trong tệp cấu hình, bạn có thể tham khảo tài liệu chính thức của TypeScript.
Bạn đã hoàn tất việc thiết lập dự án TypeScript cơ bản bằng npm
. Tiếp theo, bạn sẽ thiết lập cơ sở dữ liệu PostgreSQL bằng Docker và kết nối Prisma với nó.
Bước 2: Thiết lập Prisma với PostgreSQL
Trong bước này, bạn sẽ cài đặt Prisma CLI, tạo tệp schema đầu tiên của Prisma, thiết lập PostgreSQL bằng Docker và kết nối Prisma với cơ sở dữ liệu đó.
Tệp Prisma schema là tệp cấu hình chính của Prisma và chứa mô hình cơ sở dữ liệu của bạn.
Hãy bắt đầu bằng cách cài đặt Prisma CLI với lệnh sau:
$ npm install prisma --save-dev
Bạn nên cài đặt Prisma CLI cục bộ trong từng dự án thay vì cài đặt toàn cục. Việc này giúp tránh xung đột phiên bản nếu bạn có nhiều dự án sử dụng Prisma trên cùng một máy.
Tiếp theo, bạn sẽ thiết lập cơ sở dữ liệu PostgreSQL bằng Docker. Tạo một tệp Docker Compose mới với lệnh sau:
$ nano docker-compose.yml
Bây giờ hãy thêm đoạn mã sau vào tệp vừa tạo:
version: '3.8'
services:
postgres:
image: postgres:10.3
restart: always
environment:
- POSTGRES_USER=sammy
- POSTGRES_PASSWORD=your_password
volumes:
- postgres:/var/lib/postgresql/data
ports:
- '5432:5432'
volumes:
postgres:
Tệp Docker Compose này cấu hình một cơ sở dữ liệu PostgreSQL có thể được truy cập thông qua cổng 5432
của container Docker. Thông tin đăng nhập cơ sở dữ liệu hiện được đặt là sammy
(tên người dùng) và your_password
(mật khẩu). Bạn có thể điều chỉnh thông tin đăng nhập này thành tên người dùng và mật khẩu mà bạn muốn. Lưu và thoát khỏi tệp.
Với cấu hình này, hãy khởi chạy máy chủ cơ sở dữ liệu PostgreSQL bằng lệnh sau:
$ docker-compose up -d
Kết quả đầu ra của lệnh này sẽ tương tự như sau:
Output
Pulling postgres (postgres:10.3)...
10.3: Pulling from library/postgres
f2aa67a397c4: Pull complete
6de83ca23e55: Pull complete
. . .
Status: Downloaded newer image for postgres:10.3
Creating my-blog_postgres_1 ... done
Bạn có thể xác minh rằng máy chủ cơ sở dữ liệu đang chạy bằng lệnh sau:
$ docker ps
Lệnh này sẽ in ra nội dung tương tự như sau:
Output
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
8547f8e007ba postgres:10.3 "docker-entrypoint.s…" 3 seconds ago Up 2 seconds 0.0.0.0:5432->5432/tcp my-blog_postgres_1
Khi máy chủ cơ sở dữ liệu đã chạy, bạn có thể tạo thiết lập Prisma của mình. Chạy lệnh sau từ Prisma CLI:
$ npx prisma init
Lệnh này sẽ in ra nội dung như sau:
Output
✔ Your Prisma schema was created at prisma/schema.prisma.
You can now open it in your favorite editor.
Bạn nên thêm tiền tố npx
trước mọi lệnh gọi Prisma CLI để đảm bảo rằng phiên bản Prisma cục bộ của bạn đang được sử dụng.
Sau khi bạn chạy lệnh, Prisma CLI sẽ tạo một thư mục mới có tên là prisma
trong dự án của bạn. Bên trong đó, bạn sẽ tìm thấy một tệp schema.prisma
, đây là tệp cấu hình chính cho dự án Prisma của bạn (bao gồm mô hình dữ liệu). Lệnh này cũng thêm một tệp dotenv có tên .env
vào thư mục gốc, nơi bạn sẽ định nghĩa URL kết nối cơ sở dữ liệu của mình.
Để đảm bảo Prisma biết vị trí của cơ sở dữ liệu, hãy mở tệp .env
và điều chỉnh biến môi trường DATABASE_URL
.
Trước tiên, hãy mở tệp .env
:
$ nano .env
Bây giờ bạn có thể cập nhật biến môi trường như sau:
DATABASE_URL="postgresql://sammy:your_password@localhost:5432/my-blog?schema=public"
Hãy đảm bảo bạn thay đổi thông tin đăng nhập cơ sở dữ liệu thành các thông tin đã chỉ định trong tệp Docker Compose. Để tìm hiểu thêm về định dạng của chuỗi kết nối, hãy truy cập tài liệu Prisma.
Sau khi hoàn tất, hãy lưu và thoát khỏi tệp.
Ở bước này, bạn đã thiết lập cơ sở dữ liệu PostgreSQL bằng Docker, cài đặt Prisma CLI và kết nối Prisma với cơ sở dữ liệu thông qua biến môi trường. Trong phần tiếp theo, bạn sẽ định nghĩa mô hình dữ liệu và tạo các bảng trong cơ sở dữ liệu.
Bước 3: Định nghĩa mô hình dữ liệu và tạo bảng cơ sở dữ liệu
Trong bước này, bạn sẽ định nghĩa mô hình dữ liệu trong tệp schema.prisma. Mô hình dữ liệu này sau đó sẽ được ánh xạ sang cơ sở dữ liệu bằng Prisma Migrate, công cụ sẽ tạo và gửi các câu lệnh SQL để tạo các bảng tương ứng với mô hình dữ liệu. Vì bạn đang xây dựng một ứng dụng blog, các thực thể chính của ứng dụng sẽ là người dùng (users) và bài viết (posts).
Prisma sử dụng ngôn ngữ mô hình hóa dữ liệu riêng của nó để định nghĩa cấu trúc dữ liệu ứng dụng.
Đầu tiên, mở tệp schema.prisma
của bạn bằng lệnh sau:
$ nano prisma/schema.prisma
Bây giờ, hãy thêm các định nghĩa mô hình sau vào tệp schema.prisma
. Bạn có thể đặt các mô hình này ở cuối tệp, ngay sau khối generator client
:
. . .
model User {
id Int @default(autoincrement()) @id
email String @unique
name String?
posts Post[]
}
model Post {
id Int @default(autoincrement()) @id
title String
content String?
published Boolean @default(false)
author User? @relation(fields: [authorId], references: [id])
authorId Int?
}
Bạn đang định nghĩa hai mô hình: User
và Post
. Mỗi mô hình này có một số trường đại diện cho các thuộc tính của mô hình. Các mô hình này sẽ được ánh xạ thành các bảng trong cơ sở dữ liệu; các trường tương ứng với các cột riêng lẻ.
Giữa hai mô hình có một quan hệ một-nhiều, được chỉ định bởi các trường quan hệ posts
và author
trong User
và Post
. Điều này có nghĩa là một người dùng có thể liên kết với nhiều bài viết.
Hãy lưu và thoát tệp.
Với các mô hình này đã được thiết lập, giờ bạn có thể tạo các bảng tương ứng trong cơ sở dữ liệu bằng cách sử dụng Prisma Migrate. Trong terminal của bạn, hãy chạy lệnh sau:
$ npx prisma migrate dev --name init
Lệnh này sẽ tạo một bản ghi migration SQL mới trên hệ thống tệp của bạn và áp dụng nó vào cơ sở dữ liệu. Tùy chọn --name init
được thêm vào lệnh dùng để đặt tên cho migration và sẽ được sử dụng làm tên thư mục chứa migration được tạo ra.
Kết quả đầu ra của lệnh sẽ tương tự như sau:
Output
Environment variables loaded from .env
Prisma schema loaded from prisma/schema.prisma
Datasource "db": PostgreSQL database "my-blog", schema "public" at "localhost:5432"
PostgreSQL database my-blog created at localhost:5432
The following migration(s) have been created and applied from new schema changes:
migrations/
└─ 20201209084626_init/
└─ migration.sql
Running generate... (Use --skip-generate to skip the generators)
✔ Generated Prisma Client (2.13.0) to ./node_modules/@prisma/client in 75ms
Tệp migration SQL trong thư mục prisma/migrations/20201209084626_init/migration.sql
chứa các câu lệnh sau đã được thực thi trên cơ sở dữ liệu (phần được đánh dấu trong tên tệp có thể khác nhau tùy vào thiết lập của bạn):
-- CreateTable
CREATE TABLE "User" (
"id" SERIAL,
"email" TEXT NOT NULL,
"name" TEXT,
PRIMARY KEY ("id")
);
-- CreateTable
CREATE TABLE "Post" (
"id" SERIAL,
"title" TEXT NOT NULL,
"content" TEXT,
"published" BOOLEAN NOT NULL DEFAULT false,
"authorId" INTEGER,
PRIMARY KEY ("id")
);
-- CreateIndex
CREATE UNIQUE INDEX "User.email_unique" ON "User"("email");
-- AddForeignKey
ALTER TABLE "Post" ADD FOREIGN KEY("authorId")REFERENCES "User"("id") ON DELETE SET NULL ON UPDATE CASCADE;
Bạn cũng có thể tùy chỉnh tệp migration SQL được tạo nếu bạn thêm tùy chọn --create-only
vào lệnh prisma migrate dev
; ví dụ, bạn có thể thiết lập trigger hoặc sử dụng các tính năng khác của cơ sở dữ liệu bên dưới.
Trong bước này, bạn đã định nghĩa mô hình dữ liệu trong tệp schema của Prisma và tạo các bảng tương ứng trong cơ sở dữ liệu bằng Prisma Migrate. Trong bước tiếp theo, bạn sẽ cài đặt Prisma Client vào dự án để có thể truy vấn cơ sở dữ liệu.
Bước 4: Khám phá các truy vấn với Prisma Client trong một script đơn giản
Prisma Client là một trình xây dựng truy vấn được tạo tự động, an toàn theo kiểu dữ liệu, cho phép bạn lập trình việc đọc và ghi dữ liệu từ cơ sở dữ liệu trong ứng dụng Node.js hoặc TypeScript. Bạn sẽ sử dụng nó để truy cập cơ sở dữ liệu trong các route của REST API, thay thế cho ORM truyền thống, truy vấn SQL thuần, lớp truy cập dữ liệu tự viết, hoặc bất kỳ phương thức giao tiếp nào khác với cơ sở dữ liệu.
Trong bước này, bạn sẽ cài đặt Prisma Client và làm quen với các truy vấn mà bạn có thể thực hiện với nó. Trước khi triển khai các route cho REST API ở các bước tiếp theo, bạn sẽ khám phá một số truy vấn của Prisma Client thông qua một script có thể chạy được.
Đầu tiên, cài đặt Prisma Client trong thư mục dự án bằng gói npm
của Prisma Client:
$ npm install @prisma/client
Tiếp theo, tạo một thư mục mới có tên là src
, thư mục này sẽ chứa các tệp mã nguồn của bạn:
$ mkdir src
Tạo một tệp TypeScript bên trong thư mục mới đó:
$ nano src/index.ts
Tất cả các truy vấn của Prisma Client đều trả về promise
, vì vậy bạn cần await
chúng trong mã của mình. Điều này yêu cầu bạn phải đặt truy vấn bên trong một hàm async
.
Trong tệp src/index.ts
, hãy thêm đoạn mã khởi tạo sau với một hàm async
được thực thi trực tiếp trong script:
import { PrismaClient } from '@prisma/client'
const prisma = new PrismaClient()
async function main() {
// ... your Prisma Client queries will go here
}
main()
.catch((e) => console.error(e))
.finally(async () => await prisma.$disconnect())
Giải thích nhanh về đoạn code mẫu:
- Bạn import
PrismaClient
từ gói@prisma/client npm
đã được cài đặt trước đó. - Bạn khởi tạo một instance của PrismaClient và gán nó vào biến
prisma
. - Bạn định nghĩa một hàm
async
có tên làmain
, nơi bạn sẽ viết các truy vấn Prisma Client. - Bạn gọi hàm
main
, đồng thời xử lý các lỗi có thể xảy ra và đảm bảo rằng Prisma Client sẽ đóng kết nối với cơ sở dữ liệu thông quaprisma.$disconnect()
.
Với hàm main
đã sẵn sàng, bạn có thể bắt đầu thêm các truy vấn của Prisma Client vào script. Hãy cập nhật index.ts
để thêm các dòng được đánh dấu trong hàm main
như sau:
import { PrismaClient } from '@prisma/client'
const prisma = new PrismaClient()
async function main() {
const newUser = await prisma.user.create({
data: {
name: 'Alice',
email: 'alice@prisma.io',
posts: {
create: {
title: 'Hello World',
},
},
},
})
console.log('Created new user: ', newUser)
const allUsers = await prisma.user.findMany({
include: { posts: true },
})
console.log('All users: ')
console.dir(allUsers, { depth: null })
}
main()
.catch((e) => console.error(e))
.finally(async () => await prisma.$disconnect())
Trong đoạn code này, bạn đang sử dụng hai truy vấn của Prisma Client:
create
: Tạo một bản ghi mới trong bảngUser
. Bạn sử dụng một truy vấn ghi lồng nhau (nested write query) để tạo đồng thời cả bản ghiUser
vàPost
trong cùng một truy vấn.findMany
: Đọc tất cả các bản ghi hiện có trong bảngUser
từ cơ sở dữ liệu. Bạn sử dụng tùy chọninclude
để đồng thời tải thêm các bản ghiPost
có liên quan đến mỗi bản ghiUser
.
Lưu và đóng tệp.
Bây giờ, hãy chạy script bằng lệnh sau:
$ npx ts-node src/index.ts
Bạn sẽ nhận được kết quả đầu ra như sau trong terminal:
Output
Created new user: { id: 1, email: 'alice@prisma.io', name: 'Alice' }
[
{
id: 1,
email: 'alice@prisma.io',
name: 'Alice',
posts: [
{
id: 1,
title: 'Hello World',
content: null,
published: false,
authorId: 1
}
]
}
Ghi chú: Nếu bạn đang sử dụng giao diện đồ họa cơ sở dữ liệu (GUI), bạn có thể xác minh dữ liệu đã được tạo bằng cách kiểm tra các bảng User
và Post
. Ngoài ra, bạn cũng có thể khám phá dữ liệu bằng Prisma Studio bằng cách chạy npx prisma studio
.
Bạn vừa sử dụng Prisma Client để đọc và ghi dữ liệu trong cơ sở dữ liệu. Trong các bước tiếp theo, bạn sẽ triển khai các route cho một REST API mẫu.
Bước 5: Triển khai route đầu tiên cho REST API
Trong bước này, bạn sẽ cài đặt Express vào ứng dụng của mình. Express là một framework web phổ biến cho Node.js, sẽ được dùng để triển khai các route REST API. Route đầu tiên bạn sẽ xây dựng cho phép truy xuất tất cả người dùng thông qua yêu cầu GET. Dữ liệu người dùng sẽ được lấy từ cơ sở dữ liệu thông qua Prisma Client.
Cài đặt Express bằng lệnh sau:
$ npm install express
Vì bạn đang sử dụng TypeScript, bạn cũng nên cài đặt các kiểu định nghĩa (type definitions) tương ứng dưới dạng phụ thuộc phát triển. Chạy lệnh sau:
$ npm install @types/express --save-dev
Sau khi đã cài đặt các thư viện cần thiết, bạn có thể bắt đầu thiết lập ứng dụng Express của mình.
Mở lại tệp mã nguồn chính:
$ nano src/index.ts
Bây giờ hãy xóa toàn bộ nội dung trong index.ts
và thay thế bằng đoạn mã sau để khởi động REST API:
import { PrismaClient } from '@prisma/client'
import express from 'express'
const prisma = new PrismaClient()
const app = express()
app.use(express.json())
// ... your REST API routes will go here
app.listen(3000, () =>
console.log('REST API server ready at: <http://localhost:3000>'),
)
Dưới đây là phần tóm tắt nhanh đoạn mã:
- Bạn import
PrismaClient
vàexpress
từ các gói npm tương ứng. - Bạn khởi tạo
PrismaClient
bằng cách gọi hàm tạo và tạo một instance có tên làprisma
. - Bạn tạo ứng dụng Express bằng cách gọi
express()
. - Bạn thêm middleware
express.json()
để Express có thể xử lý dữ liệu JSON một cách chính xác. - Bạn khởi động server trên cổng
3000
.
Bây giờ bạn có thể triển khai route đầu tiên của mình. Giữa lệnh gọi app.use
và app.listen
, hãy thêm các dòng được tô sáng để tạo một route app.get
:
. . .
app.use(express.json())
app.get('/users', async (req, res) => {
const users = await prisma.user.findMany()
res.json(users)
})
app.listen(3000, () =>
console.log('REST API server ready at: <http://localhost:3000>'),
)
Sau khi thêm xong, hãy lưu và thoát khỏi tệp. Sau đó, khởi động máy chủ web cục bộ của bạn bằng lệnh sau:
$ npx ts-node src/index.ts
Bạn sẽ nhận được kết quả đầu ra như sau:
Output
REST API server ready at: <http://localhost:3000>
Để truy cập route /users
, bạn có thể mở trình duyệt và truy cập địa chỉ http://localhost:3000/users
hoặc sử dụng bất kỳ công cụ HTTP client nào khác.
Trong hướng dẫn này, bạn sẽ kiểm thử tất cả các route của REST API bằng công cụ curl
, một HTTP client hoạt động trên dòng lệnh.
Lưu ý: Nếu bạn muốn sử dụng công cụ có giao diện đồ họa (GUI), bạn có thể chọn các lựa chọn như Hoppscotch hoặc Postman.
Để kiểm thử route của bạn, hãy mở một cửa sổ hoặc tab terminal mới (để máy chủ web cục bộ vẫn tiếp tục chạy) và thực thi lệnh sau:
$ curl <http://localhost:3000/users>
Bạn sẽ nhận được dữ liệu người dùng (User) đã tạo ở bước trước:
Output
[{"id":1,"email":"alice@prisma.io","name":"Alice"}]
Lần này, mảng posts
sẽ không được trả về vì bạn không truyền tùy chọn include
vào lệnh gọi findMany
trong phần xử lý route /users
.
Bạn vừa hoàn thành route REST API đầu tiên tại địa chỉ /users
. Trong bước tiếp theo, bạn sẽ triển khai các route REST API còn lại để mở rộng chức năng cho API của mình.
Bước 6: Triển khai các Route REST API còn lại
Ở bước này, bạn sẽ triển khai các route REST API còn lại cho ứng dụng blog của mình. Sau khi hoàn tất, máy chủ web của bạn sẽ hỗ trợ các loại yêu cầu: GET
, POST
, PUT
và DELETE
.
Các route bạn sẽ triển khai bao gồm những tùy chọn sau:
HTTP Method | Route | Description |
---|---|---|
GET |
/feed |
Lấy tất cả các bài viết đã được xuất bản. |
GET |
/post/:id |
Lấy một bài viết cụ thể theo ID. |
POST |
/user |
Tạo một người dùng mới. |
POST |
/post |
Tạo một bài viết mới ở trạng tái nháp. |
PUT |
/post/publish/:id |
Cập nhật bài viết để trường published chuyển thành true . |
DELETE |
post/:id |
Xóa một bài viết theo ID. |
Bạn sẽ triển khai hai route GET
còn lại trước.
Bạn có thể dừng máy chủ bằng cách nhấn tổ hợp phím CTRL + C
****trên bàn phím. Sau đó, mở tệp index.ts
để chỉnh sửa:
$ nano src/index.ts
Tiếp theo, hãy thêm các dòng được tô sáng ngay sau phần cài đặt route app.get
:
. . .
app.get('/feed', async (req, res) => {
const posts = await prisma.post.findMany({
where: { published: true },
include: { author: true }
})
res.json(posts)
})
app.get(`/post/:id`, async (req, res) => {
const { id } = req.params
const post = await prisma.post.findUnique({
where: { id: Number(id) },
})
res.json(post)
})
app.listen(3000, () =>
console.log('REST API server ready at: <http://localhost:3000>'),
)
Đoạn mã này triển khai các route API cho hai yêu cầu GET
:
/feed
: Trả về danh sách các bài viết đã được xuất bản./post/:id
: Trả về một bài viết cụ thể dựa trên ID.
Prisma Client được sử dụng trong cả hai phần cài đặt.
Trong route /feed
, truy vấn gửi đi thông qua Prisma Client sẽ lọc tất cả các bản ghi Post
có cột published
bằng true
. Ngoài ra, truy vấn cũng sử dụng thuộc tính include
để lấy thêm thông tin tác giả (author) liên quan cho từng bài viết được trả về.
Trong route /post/:id
, bạn truyền ID lấy từ đường dẫn URL để truy xuất một bản ghi Post
cụ thể từ cơ sở dữ liệu.
Hãy lưu và thoát khỏi tệp. Sau đó, khởi động lại máy chủ bằng lệnh sau:
$ npx ts-node src/index.ts
Để kiểm thử route /feed
, bạn có thể sử dụng lệnh curl
sau trong cửa sổ terminal thứ hai:
$ curl <http://localhost:3000/feed>
Vì hiện tại chưa có bài viết nào được xuất bản, nên phản hồi sẽ là một mảng trống:
Output
[]
Để kiểm thử route /post/:id
, bạn có thể sử dụng lệnh curl
sau:
$ curl <http://localhost:3000/post/1>
Lệnh này sẽ trả về bài viết mà bạn đã tạo trước đó:
Output
{"id":1,"title":"Hello World","content":null,"published":false,"authorId":1}
Tiếp theo, bạn sẽ triển khai hai route POST
. Trong cửa sổ terminal ban đầu, hãy dừng máy chủ bằng tổ hợp phím CTRL+C
, sau đó mở lại tệp index.ts
để chỉnh sửa:
$ nano src/index.ts
Thêm các dòng mã được tô sáng vào index.ts
, sau phần cài đặt của ba route GET
:
. . .
app.post(`/user`, async (req, res) => {
const result = await prisma.user.create({
data: { ...req.body },
})
res.json(result)
})
app.post(`/post`, async (req, res) => {
const { title, content, authorEmail } = req.body
const result = await prisma.post.create({
data: {
title,
content,
published: false,
author: { connect: { email: authorEmail } },
},
})
res.json(result)
})
app.listen(3000, () =>
console.log('REST API server ready at: <http://localhost:3000>'),
)
Đoạn mã này triển khai các route API cho hai yêu cầu POST
:
/user
: Tạo một người dùng mới trong cơ sở dữ liệu./post
: Tạo một bài viết mới trong cơ sở dữ liệu.
Cũng như trước, Prisma Client được sử dụng trong cả hai phần cài đặt. Trong route /user
, bạn truyền trực tiếp các giá trị từ phần thân (body) của yêu cầu HTTP vào truy vấn create
của Prisma Client.
Route /post
phức tạp hơn một chút. Bạn không thể truyền trực tiếp các giá trị từ body của yêu cầu HTTP, mà cần trích xuất thủ công chúng trước, sau đó mới truyền vào truy vấn của Prisma Client. Lý do là cấu trúc của JSON trong phần thân yêu cầu không khớp với cấu trúc mà Prisma Client mong đợi, vì vậy bạn cần tự tạo lại cấu trúc dữ liệu đúng định dạng.
Sau khi hoàn tất, lưu và thoát khỏi tệp.
Sau đó, khởi động lại máy chủ bằng lệnh:
$ npx ts-node src/index.ts
Để tạo một người dùng mới thông qua route /user
, bạn có thể gửi yêu cầu POST bằng lệnh curl
sau:
$ curl -X POST -H "Content-Type: application/json" -d '{"name":"Bob", "email":"bob@prisma.io"}' <http://localhost:3000/user>
Lệnh này sẽ tạo một người dùng mới trong cơ sở dữ liệu và in ra kết quả như sau:
Output
{"id":2,"email":"bob@prisma.io","name":"Bob"}
Để tạo một bài viết mới thông qua route /post
, bạn có thể gửi yêu cầu POST bằng lệnh curl
sau:
$ curl -X POST -H "Content-Type: application/json" -d '{"title":"I am Bob", "authorEmail":"bob@prisma.io"}' <http://localhost:3000/post>
Lệnh này sẽ tạo một bài viết mới trong cơ sở dữ liệu và liên kết nó với người dùng có email là bob@prisma.io
. Sau đó, kết quả sẽ được in ra như sau:
Output
{"id":2,"title":"I am Bob","content":null,"published":false,"authorId":2}
Cuối cùng, bạn sẽ triển khai các route PUT
và DELETE
. Hãy dừng máy chủ đang chạy, sau đó mở tệp index.ts
bằng lệnh sau:
$ nano src/index.ts
Tiếp theo, sau phần triển khai của hai route POST
, hãy thêm các dòng mã được tô sáng:
. . .
app.put('/post/publish/:id', async (req, res) => {
const { id } = req.params
const post = await prisma.post.update({
where: { id: Number(id) },
data: { published: true },
})
res.json(post)
})
app.delete(`/post/:id`, async (req, res) => {
const { id } = req.params
const post = await prisma.post.delete({
where: { id: Number(id) },
})
res.json(post)
})
app.listen(3000, () =>
console.log('REST API server ready at: <http://localhost:3000>'),
)
Đoạn mã này triển khai các route API cho một yêu cầu PUT
và một yêu cầu DELETE
:
/post/publish/:id
(PUT
): Xuất bản một bài viết dựa trên ID./post/:id
(DELETE
): Xoá một bài viết dựa trên ID.
Một lần nữa, Prisma Client được sử dụng trong cả hai phần cài đặt.
Trong route /post/publish/:id
, ID của bài viết cần xuất bản được lấy từ URL và truyền vào truy vấn update
của Prisma Client. Tương tự, trong route /post/:id
, để xoá một bài viết khỏi cơ sở dữ liệu, ID cũng được lấy từ URL và truyền vào truy vấn delete
của Prisma Client.
Sau khi hoàn tất, lưu và thoát khỏi tệp.
Khởi động lại máy chủ bằng lệnh:
$ npx ts-node src/index.ts
Bạn có thể kiểm thử route PUT
bằng lệnh curl
sau:
$ curl -X PUT <http://localhost:3000/post/publish/2>
Lệnh này sẽ xuất bản bài viết có ID là 2. Nếu bạn gửi lại yêu cầu GET đến route /feed
, bài viết này giờ sẽ được hiển thị trong kết quả phản hồi.
Cuối cùng, bạn có thể kiểm thử route DELETE
bằng lệnh curl
sau:
$ curl -X DELETE <http://localhost:3000/post/1>
Lệnh này sẽ xoá bài viết có ID là 1. Để xác nhận rằng bài viết này đã bị xoá, bạn có thể gửi lại yêu cầu GET đến route /post/1
với lệnh curl
sau:
$ curl <http://localhost:3000/post/1>
Trong bước này, bạn đã triển khai toàn bộ các route REST API còn lại cho ứng dụng blog của mình. Hiện tại, API đã có thể xử lý các yêu cầu GET
, POST
, PUT
và DELETE
, đồng thời cho phép đọc và ghi dữ liệu vào cơ sở dữ liệu.
Kết luận
Trong bài viết này, bạn đã xây dựng một máy chủ REST API với nhiều route khác nhau để tạo, đọc, cập nhật và xoá dữ liệu người dùng và bài viết cho một ứng dụng blog mẫu. Bên trong các route API, bạn sử dụng Prisma Client để thực hiện các truy vấn tương ứng đến cơ sở dữ liệu.
Các bước tiếp theo, bạn có thể:
- Triển khai thêm các route API mới.
- Mở rộng schema cơ sở dữ liệu bằng Prisma Migrate.
- Truy cập tài liệu Prisma để tìm hiểu sâu hơn về các tính năng khác.
- Khám phá các dự án mẫu sẵn sàng sử dụng với GraphQL, gRPC và các API khác trong kho prisma-examples.