摘要:实现一套基于 nodejs + Mongoose + Express 的 API 接口服务,实现对后端 MongoDB 数据库的增删改查(CRUD)
架构原理
各部分功能
1、MongoDB ,一款流行的 NOSQL 文档数据库,用于数据的存储。
2、Nodejs,一款 javascript 运行环境,提供 NPM 等包管理工具。
3、Express,一款 WEB 框架,用于接收和发送 HTTP 请求,在 Nodejs 环境运行。
4、Mongoose,一款 MongoDB 驱动引擎,可以与数据库进行通信交互,在 Nodejs 环境运行。
可选:nodemon,实现在保存工程文件后,自动重启服务。
流程原理
1、在 Nodejs 环境当中,使用 Mongoose 连接 MongoDB 数据库;
2、数据库连接成功后,启动 Express 框架服务;
3、通过定义的 Express 路由与 Mongoose 模型,与 MongoDB 数据库通信;
4、通过 API 接口进行数据增删改查;
环境配置
说明:以下操作均基于 M1 芯片 MacBook Pro
(1)安装 MongoDB
详见:Install MongoDB — MongoDB Manual
(2)安装 Nodejs
详见:下载 | Node.js 中文网
(3)安装 Express 、Mongoose、nodemon
1
| npm install express mongoose nodemon
|
创建项目
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| //创建目录 mkdir mongo-api
//进入目录 cd mongo-api
//初始化 nodejs npm init -y
//查看当前目录文件,应包含 package.json ls
//安装 Express 、Mongoose、nodemon npm install express mongoose nodemon
//查看当前目录文件,应包含 node_modules ls
//使用vscode打开当前目录(需提前配置 vscode) code .
|
搭建基本 HTTP 访问服务
(1)创建 Express 访问入口文件 /app.js
:
1 2 3 4 5 6 7 8 9 10 11 12 13
| const express = require("express");
const app = express();
const port = 3000;
app.listen(port, "127.0.0.1", (req, res) => { console.log(`服务启动,运行在: http://127.0.0.1:${port} `); });
|
(2) 修改 package.json 添加启动脚本命令
1 2 3 4 5
| "scripts": { "test": "echo \"Error: no test specified\" && exit 1", "start": "nodemon app.js" },
|
(3)启动服务
1 2 3 4 5
| npm start
//终端将自动打印日志: [nodemon] starting `node app.js` 服务启动,运行在: http://127.0.0.1:3000
|
此时使用浏览器访问:http://127.0.0.1:3000 ,将显示:Cannot GET /
(原因是还没定义处理函数)
搭建 MongoDB 基础访问服务
(1)在 /app.js
主入口文件 ,引入 Mongoose 包并配置连接
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| const express = require("express"); const mongoose = require("mongoose");
mongoose .connect("mongodb://127.0.0.1:27017/mydb") .then(() => { const app = express(); const port = 3000; app.listen(port, "127.0.0.1", (req, res) => { console.log(`服务启动,运行在: http://127.0.0.1:${port} `); }); }) .catch((err) => { console.log("数据库连接失败"); });
|
(2) 创建 mongodb 模型文件 /models/blog.js
1 2 3 4 5 6 7 8 9 10 11 12
| const { set } = require("express/lib/application"); const mongoose = require("mongoose");
const schma = mongoose.schma({ title: String, content: String, });
module.exports = mongoose.model("blog", schma);
|
(3)创建 Express 路由文件:/routes.js
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| const express = require("express"); const blog = require("./models/blog");
const router = express.Router();
router.get("/blog", async (req, res) => {
const bloglist = await blog.find(); res.send(bloglist); });
module.exports = router;
|
(4) 将路由文件引入到主入口文件 /app.js
中
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
| const express = require("express"); const mongoose = require("mongoose");
const routes = require("./routes");
mongoose .connect("mongodb://127.0.0.1:27017/mydb") .then(() => { const app = express();
app.use(express.json());
app.use("/api", routes);
const port = 3000; app.listen(port, "127.0.0.1", (req, res) => { console.log(`服务启动,运行在: http://127.0.0.1:${port} `); }); }) .catch((err) => { console.log("数据库连接失败"); });
|
保存项目,访问:http://127.0.0.1:3000/api/blog 呈现空列表(此时数据库没有文件):
完善查看、创建、修改、删除接口
(1)创建数据,在 /routes.js
get 请求块下补充内容:
1 2 3 4 5 6 7 8 9 10 11 12
| router.post("/blog", async (req, res) => {
const postdata = new blog({ title: req.body.title, content: req.body.content, }); await postdata.save(); res.send(postdata); });
|
(2)查找指定 ID 文档数据,在 /routes.js
post 请求块下补充内容:
1 2 3 4 5 6 7 8 9 10 11 12 13
| router.get("/blog/:id", async (req, res) => {
try { const oneid = req.params.id; const blogdata = await blog.findOne({ _id: oneid }); res.send(blogdata); } catch { res.status(404); res.send({ error: "没有这条数据" }); } });
|
(3)更新指定 ID 文档数据,在 /routes.js
get 块下补充内容:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| router.post("/blog/:id", async (req, res) => {
try { const oneid = req.params.id;
const blogdata = await blog.findOne({ _id: oneid });
if (req.body.title) { blogdata.title = req.body.title; }
if (req.body.content) { blogdata.content = req.body.content; }
await blogdata.save(); res.send(blogdata); } catch { res.status(404); res.send({ error: "没有这条数据" }); } });
|
(4)删除指定 ID 文档数据,在 /routes.js
post 块下补充内容:
1 2 3 4 5 6 7 8 9 10 11
| //删除指定ID数据 delete 请求 router.delete("/blog/:id", async (req,res)=>{ // 构建异步回调函数 try{ const oneid = req.params.id //提取请求当中的ID await blog.deleteOne({_id:oneid}) //根据ID删除文档 res.status(204).send() //指定返回状态码 }catch{ res.status(404) //处理没有数据的情况 res.send({error:"没有这条数据"}) } })
|
完整版 /routes.js
内容
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75
| const express = require("express"); const blog = require("./models/blog");
const router = express.Router();
router.get("/blog", async (req, res) => {
const bloglist = await blog.find(); res.send(bloglist); });
router.post("/blog", async (req, res) => { const postdata = new blog({ title: req.body.title, content: req.body.content, }); await postdata.save(); res.send(postdata); });
router.get("/blog/:id", async (req, res) => { try { const oneid = req.params.id; const blogdata = await blog.findOne({ _id: oneid }); res.send(blogdata); } catch { res.status(404); res.send({ error: "没有这条数据" }); } });
router.post("/blog/:id", async (req, res) => { try { const oneid = req.params.id; const blogdata = await blog.findOne({ _id: oneid }); if (req.body.title) { blogdata.title = req.body.title; } if (req.body.content) { blogdata.content = req.body.content; } await blogdata.save(); res.send(blogdata); } catch { res.status(404); res.send({ error: "没有这条数据" }); } });
router.delete("/blog/:id", async (req, res) => { try { const oneid = req.params.id; await blog.deleteOne({ _id: oneid }); res.status(204).send(); } catch { res.status(404); res.send({ error: "没有这条数据" }); } });
module.exports = router;
|