前端工程师的后端基础知识:使用 NodeJS、Prisma 和 PostgreSQL 深入研究 SQL 和 API
本文是为没有任何后端经验的人撰写的,因此任何人都可以从中学习!
最近在做一个全栈项目,我发现了一些很棒的工具,可以帮助开发人员轻松生成数据库结构,从而处理大部分复杂问题。在本文中,我们将express
使用 NodeJS、Prisma 和 PostgreSQL 创建一个简单的 API(别被一堆技术吓到!)
SQL 与 NoSQL
SQL 和 NoSQL 是两种类型的数据库。
SQL
SQL 使用数据表,类似于 Excel 或 Google Sheets 电子表格。在关系数据库中,表可以通过关系字段相互链接。
例如,假设有一个存储汽车及其车主信息的数据库。它的结构可以如下:
owner
桌子
ID | 姓名 | 年龄 | 卡号 |
---|---|---|---|
1 | 史蒂文 | 24 | 143 |
2 | 鲍勃 | 41 | 144 |
3 | 莎拉 | 三十五 | 145 |
car
桌子
ID | 制作 | 模型 | 年 | 所有者ID |
---|---|---|---|---|
143 | 雪佛兰 | 克尔维特 | 2020 | 1 |
144 | 本田 | 思域 | 2010 | 2 |
145 | 现代 | 栅栏 | 2017 | 3 |
在此示例中,表carId
中的列owner
指的是表id
的列car
。表ownerId
的列car
指的是id
所有者表的列。id
是每个表中的主键,而ownerId
和carId
是“外键”,因为它们指的是不同表的主键。
NoSQL
NoSQL 是一种基于文档的数据库,其中的文档通常类似于 JSON 对象。这种结构对于前端开发人员来说可能更为熟悉,但这两种数据库各有优缺点。本教程将使用 SQL,因此我不会在这里过多地讨论 NoSQL。您可以通过搜索“比较”来在线了解更多关于它们的区别!
PostgreSQL 和数据库安装
PostgreSQL(有时也称为 Postgres)是一款遵循 SQL 规范的非常流行的关系数据库。它允许我们建立带有表的数据库,并通过易于理解的关系将它们连接起来。
首先,我们将安装 Postgres,以便您可以在计算机上设置数据库。您可以在此处找到适合您操作系统的下载:https://www.postgresql.org/download/。
下载完成后,请保留默认设置。系统会要求您输入 root 用户的密码:无论您选择什么,⚠请务必记下您选择的密码⚠。默认用户名是postgres
。
安装完成后,您可以登录到本地数据库实例,并在命令行上使用它!在您的计算机上搜索一个名为 的程序psql
,它是一个终端/CMD 提示符应用程序,可让您与 Postgres 数据库进行交互。打开该程序并按 Enter 键(使用默认值)登录,然后输入您的密码。完成后,您应该会看到以下内容:
现在我们可以测试一些命令来熟悉 Postgres。首先,输入\l
,然后按 Enter 列出计算机上现有的数据库。Postgres 默认会创建一些数据库。
虽然我说过我们不会编写任何 SQL 查询,但我建议为这个项目创建一个单独的数据库。在 PSQL 中,输入CREATE DATABASE prismademo;
并按 Enter。然后,您可以使用 连接到新数据库\c prismademo
。
如果您愿意,可以花一些时间创建数据库和表 - 您可以通过搜索“如何在 psql 中创建数据库”、“如何在 psql 中创建表”等找到大量简单的指南。
⚠注意!在 PSQL 中输入的大多数 SQL 查询都需要以分号结尾。别忘了分号! ⚠
服务器设置
在普通终端或 CMD 提示符(不是 psql)中,为用于创建 API 服务器的 JavaScript 代码创建一个文件夹。我将文件夹命名为prisma-demo
. cd
,然后运行npm init
。按照初始化项目的步骤操作。在您喜欢的 IDE 中打开项目文件夹(如果您使用 VS Code,则可以在此目录中键入命令code .
以在此处打开 VS Code)。您应该会看到一个package.json
包含您刚刚输入的信息的 。
Prisma 集成
安装 Prisma
我们终于来到了基石Prisma,它将:
- 连接我们的数据库和 JS 服务器
- 在我们的数据库中为我们生成表
- 生成 JavaScript 函数和 TypeScript 类型以与我们的数据库交互(如果您不使用 TypeScript,不用担心,请继续阅读!)
首先,npm install prisma -D
安装 Prisma。
接下来,执行npx prisma
来验证 Prisma 是否已安装,然后npx prisma init
。第二个命令将在 中生成一个 Prisma 模式文件prisma/schema.prisma
,并.env
带有一个示例数据库 URL。
⚠ 接下来我们应该将 添加.env
到.gitignore
。创建一个.gitignore
包含以下内容的文件:
.env
node_modules
git init
现在,如果您愿意,您可以安全地运行并提交您的项目。
修复数据库 URL
打开你的.env
并将示例 URL 替换为以下 URL:
DATABASE_URL="postgresql://postgres:INSERTYOURPASSWORD@localhost:5432/prismademo?schema=public"
如果您之前没有创建prismademo
数据库,请用postgres
URL 中的 ? 之前的部分替换该部分。
填写 Prisma Schema
打开schema.prisma
。在这里,我们可以定义数据模型,然后使用 Prisma CLI 根据数据模型生成所需的数据库表和 JavaScript 函数。
我们将使用上面的汽车示例。假设每个人可以拥有多辆汽车,每辆汽车只能有一个车主,这意味着车主/汽车之间存在一对多关系。您可以在此处了解所有可能的关系类型:https://www.prisma.io/docs/concepts/components/prisma-schema/relations
将以下代码添加到你的 schema 中以设置模型。注意其中的关系:每个车主都有一个汽车列表,每辆车可以有一个车主,由 指定ownerId
。注意,它看起来有点类似于 GraphQL Schema!
model Owner {
// Prisma will automatically create an ID for each entry for us
id Int @id @default(autoincrement())
name String
age Int
// Each Owner can have multiple cars
Car Car[]
}
model Car {
id Int @id @default(autoincrement())
make String
model String
year Int
// Each Car can have only 1 owner
ownerId Int
owner Owner @relation(fields: [ownerId], references: [id])
}
我们使用@id
注释来表示这是此模型的主键字段。@default(autoincrement())
意味着我们在创建所有者或汽车时不需要提供 ID,它将自动分配给1 + the last ID
。
注意!有一个很棒的 VS Code 扩展可以帮助格式化和维护此文件:https://marketplace.visualstudio.com/items? itemName=Prisma.prisma
将架构迁移到数据库
现在我们已经创建了 Prisma Schema,我们需要运行一个命令,以便 Prisma 能够在数据库中实际创建此 Schema 的表。npx prisma migrate dev --name "Create initial schema"
在项目目录的终端/cmd 提示符下运行。您可以更改名称文本,但请保持描述性!(注意:如果命令在 处冻结"Running generate...
,请停止进程并运行npx prisma generate
。)
回到 PSQL 中的数据库。现在运行\dt
,你就能看到我们用 Prisma Schema 创建的表了!是不是很酷?😎
您还可以运行程序npx prisma studio
,在交互式 Web 视图中查看数据库结构。我建议您尝试一下,这样您就可以直观地看到生成的数据库!
当你运行迁移或时prisma generate
,Prisma 还会创建完全类型的 JavaScript 函数,以便我们与数据库交互,而无需手动编写任何 SQL!让我们看看如何使用这些函数来创建 API。
用于创建车主和汽车的 REST API
如果你是一名 JS 开发者,你可能已经熟悉这部分内容了。Express 是一个用于编写服务器的 NPM 包。
运行npm i express body-parser
安装 express 和 body-parser,我们将使用它来读取 API 中的 JSON 输入。
server.js
在项目根文件夹中创建一个文件。添加以下内容:
const express = require("express");
const app = express();
const bodyParser = require('body-parser')
const port = 3030;
const jsonParser = bodyParser.json()
app.listen(port, () => {
console.log(`Example app listening at http://localhost:${port}`)
})
首先,我们将创建一个 REST API 路由来同时创建用户和汽车并将它们链接在一起。
将 Prisma 客户端导入和实例添加到server.js
文件中,在任何路由之外,下面const port = ...
const { PrismaClient } = require('@prisma/client')
const prisma = new PrismaClient()
接下来,创建一个 POST 路由:
app.post('/owner', jsonParser, async (req, res) => {
})
当 Web 应用程序或 REST 客户端使用我们指定的 URL 向此 Express 服务器发送 POST 请求时,服务器将运行此功能。
我们将使用 Prisma 生成的函数在我们的数据库中创建车主和汽车。
Prisma 创建函数遵循 的形式prisma.<MODEL NAME>.create
,因此在我们的例子中我们将使用prisma.owner.create(...)
。如果您一直关注,您会看到我们的 IDE 知道我们的模型被调用owner
并自动建议它,因为 Prisma 已经从我们的模式 生成了这些函数。
Prisma 将在参数字段中为所有者模型建议字段data
,如下所示:
app.post("/owner", jsonParser, async (req, res) => {
const body = req.body
const newOwner = await prisma.owner.create({
data: {
name: body.name,
age: body.age
}
})
}
Prisma 的另一个很棒的功能是,我们可以在同一个函数调用中创建 Car 数据库条目并将其链接到此 Owner。操作如下:
const newOwner = await prisma.owner.create({
data: {
name: body.name,
age: body.age,
Car: {
create: {
make: body.car.make,
model: body.car.model,
year: body.car.year,
},
},
},
});
最后,我们将添加 try/catch 用于错误处理和响应:
app.post("/owner", jsonParser, async (req, res) => {
const body = req.body
try {
const newOwner = await prisma.owner.create({
data: {
name: body.name,
age: body.age,
Car: {
create: {
make: body.car.make,
model: body.car.model,
year: body.car.year,
},
},
},
});
res.status(200).json({owner: newOwner})
} catch (e) {
console.log(e);
res.status(503).json({error: "Failed to create Owner and Car."})
}
});
需要注意的是:我们没有在汽车 JSON 中指定 ownerId,也没有在车主 JSON 中指定 carID。由于我们在一个函数调用中将一个嵌套在另一个中创建,因此 Prisma 会帮我们关联 ID!这是通过@relation
我们在 schema 中添加的字段实现的。
测试一下
在项目目录中运行node server.js
以运行服务器。然后,您可以使用任何 HTTP 客户端来测试此 API 路由。例如,您可以使用 cURL、Postman 或带有 的 NodeJS 文件node-fetch
。
无论您如何测试它,运行类似于以下 POST 请求的请求,您都应该得到给定的响应!
如果您还想在响应中获取汽车信息,您可以include
在prisma.owner.create
调用中添加字段以告诉 Prisma 包含连接的汽车对象:
const newOwner = await prisma.owner.create({
data: {
...
},
include: {
Car: true
}
});
添加此字段后重启Node服务器,重新运行请求就可以看到创建好的汽车了!
🎉恭喜!至此,您已经设置了数据库,根据模式创建了表,并添加了 REST API 来将信息存储在数据库中。
查看您的数据库
回到psql
终端,运行TABLE "Car";
以下命令打印出 Car 表。你应该看到如下表格形式的输出:
prismademo=# TABLE "Car";
id | make | model | year | ownerId
----+-----------+----------+------+---------
1 | Chevrolet | Corvette | 2020 | 1
2 | Chevrolet | Camaro | 2020 | 2
(2 rows)
您还可以通过再次运行来查看 Prisma Studio 中的数据npx prisma studio
!
添加获取存储信息的路由
最后,我们将添加一个 REST API 路由来获取车辆信息,以便您的前端可以读取车辆数据。请求的车辆 ID 将成为 URL 的一部分。
Prisma 中的函数find___
允许我们使用过滤器来获取符合特定条件的数据库条目。我们将使用它prisma.car.findFirst(...)
来查找具有给定 ID 的第一辆汽车。
在我们添加的 POST 路由下方添加:
app.get("/car/:carId", async (req, res) => {
try {
const car = await prisma.car.findFirst({
where: {
id: Number(req.params.carId)
},
include: {
owner: true
}
})
res.status(200).json({ car });
} catch (e) {
console.log(e);
res.status(503).json({ error: "Failed to get car." });
}
});
carId
我们使用URL 中的来命名 URL 参数:carId
。我们不需要bodyParser
,因为我们不需要像创建 owner/car 时那样解析 POST 的 JSON。
我们使用它where
来告诉 Prisma 获取具有匹配 ID 的汽车。您会注意到这里也支持自动建议。我们使用Number(...)
它将 URL 参数从字符串转换为数字,因为根据我们的模式,ID 是一个 Int 类型。最后,我们使用它include
通过汽车详细信息获取车主详细信息。
重启服务器。现在你应该可以http://localhost:3030/car/1
在 Web 浏览器或 HTTP 客户端中查看你创建的第一辆汽车了!
回顾并进一步发展!
信息量很大,速度很快。到目前为止,做得很棒!
总而言之,在本教程中您将:
- 已安装 PostgreSQL
- 为您的项目创建了一个数据库
- 使用 Prisma 根据 Schema 创建数据库表
- 编写了
express
服务器 REST API - 向 API 添加了路由以创建/存储和获取数据库条目。
进一步考虑以下几点想法:
- 尝试在模式中添加新模型(可能是经销商,或者为制造商创建一个模型,而不仅仅是一个字符串)
- 新的关系类型,或者新的字段类型。比如
purchasedAt
车辆上的日期字段,或者允许一辆车拥有多个车主,并建立多对多关系。 - 添加更多 API 功能。例如,您可以添加路线,将另一辆车添加到现有车主名下,或从车主名下删除一辆车。
我绝对建议查看 Prisma 文档,尤其是不同类型的关系、数据类型、Prisma 的权衡等等:https://www.prisma.io/docs/
您也可以在这里查看我的源代码:https://github.com/aej11a/prisma-demo
感谢阅读!点击此处或Twitter关注我,获取更多更新和其他内容。如有任何问题,欢迎随时私信我!
文章来源:https://dev.to/ajones_codes/create-an-entire-backend-without-writing-a-single-sql-query-intro-to-postgres-and-prisma-for-frontend-developers-1ffl