MongoDB 是一种开源的文档型 NoSQL 数据库,数据以类 JSON 的文档形式存储,是 JavaScript 技术栈中最易上手的数据库。本讲将从零开始,依次介绍数据库基础概念、MongoDB 的启动与验证、数据库与集合的创建、新闻数据的导入,以及增删改查(CRUD)的基本操作,并为 Day 3 服务器开发所需的 Mongoose 概念做好铺垫。
什么是 Mongoose? Mongoose 是一个运行在 Node.js 服务器端的 npm 包,专门用来连接和操作 MongoDB。它把数据库里的文档映射成 JavaScript 对象,并提供统一的增删改查方法,让我们不写数据库命令、只用熟悉的 JS 语法就能操作数据。本讲只做概念铺垫(见第 5 节),Day 3 编写服务器代码时正式安装并使用。
《企业技能实习》· 新闻系统全栈项目实训
实操纪律:
mongod命令启动的窗口需保持运行,不可关闭——数据库一旦停止,后续所有操作都会失败。
上节回顾
- 三件套分工:HTML 搭骨架(用 header / main 等语义化标签对新闻页分区),CSS 管外观(盒模型 border-box、float 布局配合清除浮动、定位"子绝父相"),JS 负责交互与数据;
- 核心方法:新闻列表不是一行行写死的,而是"数组 + forEach + 模板字符串"循环渲染出来的——数据驱动页面;轮播图用 Swiper 插件实现;
- 遗留问题:渲染列表用的还是写死在代码里的假数据,改一条新闻就要改代码、重新发布页面——这正是今天引入数据库要解决的问题;
- 环境验收:按 Day 1 布置的清单,
node -v、npm -v、mongod --version均应能输出版本号,Compass 已安装,D:\mongodb\data文件夹已创建——本讲第 2 节将立即用到这些准备。
资源下载
- 新闻数据文件:
news.newsList.json(由教师统一发放)
1. 数据库基础概念
1.1 为什么需要数据库
Day 1 页面中的新闻是写死在 HTML 里的假数据(非动态更新的),存在三个无法回避的问题:
- 修改一条新闻就要修改代码,修改后还需重新发布页面;
- 数据量大时(例如数万条新闻),页面文件无法管理;
- 前台展示页与后台管理系统是两套页面,数据无法共享。
数据库(Database) 是按照特定结构组织、存储和管理数据的仓库,增、删、改、查是它的四项基本职能。
通过引入数据库的能力,可以让页面对用户展示的数据和信息实现真正的动起来。
1.2 关系型数据库与 NoSQL
SQL 是什么意思? SQL(Structured Query Language,结构化查询语言)是操作关系型数据库的标准语言,查、增、改、删都通过它完成,例如 SELECT * FROM newsList 表示"从 newsList 表中查询全部数据"。像 MySQL 这类用 SQL 操作的数据库被称为 SQL 数据库;而 MongoDB 属于 NoSQL(Not Only SQL)——不用 SQL 语句,改用 JS 风格的方法调用完成同样的操作,这正是下表对比的核心。
| MySQL(关系型) | MongoDB(文档型 NoSQL) | |
|---|---|---|
| 组织方式 | 库 → 表 → 行/列 | 库 → 集合 → 文档 |
| 数据形态 | 规整的行与列 | 一条数据类似一条 JSON |
| 操作方式 | SQL 语句 | JS 风格的方法调用 |
MongoDB 的一条数据与 JS 对象高度相似,对具备 JavaScript 基础的学习者最为友好。两种数据库在企业中都会遇到,思维方式可以互相迁移。
1.3 MongoDB 的三层结构
以下三个名称贯穿整个项目,必须准确记忆(Day 3 的代码中将原样出现):
| MongoDB 概念 | 本项目对应 | 类比 MySQL |
|---|---|---|
| 数据库 database | news |
database |
| 集合 collection | newsList |
表 table |
| 文档 document | { title, author, date, imgSrc, _id } |
行 row |
打开 news.newsList.json 观察一条真实文档,包含 5 个字段:title 标题、author 作者、date 时间、imgSrc 图片链接,以及 _id。
注意:库名
news、集合名newsList与 5 个字段名在本课程中不可改动,名称不一致是本项目最隐蔽的一类 bug。
1.4 _id:文档的唯一标识
每条文档被创建时,MongoDB 会自动为其生成唯一编号(ObjectId),相当于每条新闻的身份证号。增删改查操作均通过 _id 进行索引,精确定位某一条文档。
1.5 端口与连接地址
- MongoDB 默认运行在 27017 端口,端口是访问服务的"门牌号";
localhost表示本机;- 因此本项目的数据库地址为:
mongodb://localhost:27017/news(连接地址 + 库名)——这正是 Day 3 服务器代码中将书写的那一行。
2. 启动与验证 MongoDB
2.1 启动数据库服务
打开 cmd,执行以下命令:
# 启动 MongoDB,--dbpath 指定数据文件的存放目录
mongod --dbpath D:\mongodb\data
窗口停留在滚动的输出界面即表示数据库正在运行,不要关闭该窗口。
2.2 验证启动结果
在浏览器中访问 localhost:27017,看到以下提示即表示启动成功:
It looks like you are trying to access MongoDB over HTTP on the native driver port.
如启动失败,先阅读报错最后一行:多数情况是 D:\mongodb\data 文件夹不存在,创建后重新执行即可。
2.3 环境自查清单
| 检查项 | 命令 / 操作 | 预期结果 |
|---|---|---|
| Node | node -v |
输出版本号 |
| npm | npm -v |
输出版本号 |
| MongoDB | mongod --version |
输出版本号 |
| 数据库运行中 | 浏览器访问 localhost:27017 |
出现提示文案 |
| Compass | 连接 localhost:27017 | 左侧可见数据库列表 |
3. 创建数据库并导入新闻数据
3.1 连接 Compass
打开 MongoDB Compass,连接串保持默认 mongodb://localhost:27017,点击 Connect。
3.2 创建 news 数据库与 newsList 集合
- 点击 Create Database;
- Database Name 填写
news,Collection Name 填写newsList(一步同时创建库和第一个集合); - 点击 Create Database 完成创建。
注意:两个名称必须与 1.3 节表格完全一致。名称错误时程序不会报错,但 Day 3 的代码将连接到一个空库,查询不到任何数据。
3.3 导入新闻数据
- 进入 newsList 集合页面,点击 ADD DATA → Import JSON;
- 选择
news.newsList.json→ Import; - 通过表格视图 / JSON 视图切换按钮,分别查看两种数据展示方式。
3.4 验证导入结果
- 文档数量 ≥ 12 条;
- 随机打开一条文档,确认
title、author、date、imgSrc、_id五个字段完整。
4. 数据的增删改查(CRUD)
4.1 打开 mongosh
mongosh 是 MongoDB 的命令行客户端。本课程直接使用 Compass 下方的 _mongosh 标签页,后续所有命令都在其中执行。
4.2 查询数据(find)
// 切换到 news 数据库
use news
// 查询集合中的全部文档
db.newsList.find()
// 条件查询:作者为 深燃 的新闻
db.newsList.find({ author: "深燃" })
4.3 插入数据(insertOne)
// 插入一条自己的新闻(author 填写自己的名字)
db.newsList.insertOne({
title: "我插入的第一条新闻",
author: "你的名字",
date: "2026-09-08 10:00",
imgSrc: "https://images.tmtpost.com/uploads/images/2025/09/20250911163838524.jpg"
})
4.4 更新数据(updateOne 与 $set)
// 将自己那条新闻的标题修改为新值
db.newsList.updateOne({ author: "你的名字" }, { $set: { title: "改过标题的新闻" } })
注意:
$set不可省略。不带$set的updateOne会用新对象整条覆盖旧文档,其余字段全部丢失。动手验证:故意执行一次不带$set的更新,在 Compass 中观察文档被覆盖的结果,再从 json 文件重新导入恢复。
4.5 删除数据(deleteOne)
// 删除自己插入的那条新闻
db.newsList.deleteOne({ author: "你的名字" })
注意:
deleteOne按条件删除,条件匹配到多条时只删除第一条。正式系统中删除数据应尽量使用_id定位,避免误删。
4.6 条件查询、排序与统计
// 按 date 倒序取前 3 条
db.newsList.find().sort({ date: -1 }).limit(3)
// 标题中包含"芯片"的文档($regex 表示模糊匹配)
db.newsList.find({ title: { $regex: "芯片" } })
// 统计文档总数
db.newsList.countDocuments()
4.7 Compass 图形化操作与命令的对应
在 Compass 界面中手动编辑一条文档,再回到 mongosh 执行 find 查看——数据已发生变化。界面按钮背后执行的就是这些命令,两种方式完全等价。
5. Mongoose 概念铺垫
5.1 三层映射
Day 3 编写的 Node 服务器将通过 Mongoose 操作数据库。它是运行在服务器端、专门连接 MongoDB 的工具包,使用时遵循三层映射:
mongoose.connect("mongodb://localhost:27017/news") ← 连接哪个库
mongoose.model("List", 字段定义, "newsList") ← 对应哪个集合
dataModel.find() / create() / deleteOne() / updateOne() ← 相当于本讲的四条命令
本项目用到的字段定义:{ title: String, author: String, date: String, imgSrc: String }——与导入数据中的字段一一对应。
5.2 编写 schema-demo.js
在 D:\news 根目录新建 schema-demo.js(本讲不需要运行,Day 3 会将其合并进服务器代码):
// 服务器代码的前置部分:连接 + 模型定义
var mongoose = require("mongoose");
mongoose.connect("mongodb://localhost:27017/news");
mongoose.connection.on("open", function (err) {
if (err) { console.log("数据库连接失败"); }
else { console.log("数据库连接成功"); }
});
var dataModel = mongoose.model(
"List",
{ title: String, author: String, date: String, imgSrc: String },
"newsList"
);
此时
require会报错,因为 mongoose 包尚未安装——安装是下一讲的第一项操作。请核对代码中的news、newsList与 3.2 节创建的名称是否一致。
6. 动手练习
6.1 任务清单
| 层级 | 任务 |
|---|---|
| 基础必做 | ① 独立完成"启动 → 建库建集合 → 导入"全链路;② 在 mongosh 完成增、查(无条件与条件各一次)、改(带 $set)、删各 1 条,每步命令截图贴入日志 |
| 进阶选做 | ① 查询指定 author 的全部文档;② 使用 sort({date:-1}).limit(3) 获取最新 3 条;③ 删除 1 条数据后从 news.newsList.json 重新导入恢复 |
| 挑战加分 | ① 使用 updateMany 批量修改指定日期的文档;② 思考题(写入日志):两条新闻标题相同时,deleteOne 删除的是哪一条?如何做到"想删哪条删哪条"? |
6.2 自查清单
- [ ] 数据库命令行窗口始终在运行
- [ ] Compass 中 newsList 集合文档数 ≥ 12
- [ ] 增、查、改、删四类命令均执行成功过
- [ ] 库名、集合名与 1.3 节表格完全一致
6.3 常见问题排查
| 现象 | 常见原因 |
|---|---|
| mongod 报错退出 | D:\mongodb\data 文件夹不存在或路径拼写错误 |
| Compass 连接失败 | 数据库窗口被关闭,或 27017 端口被占用 |
| 导入 JSON 失败 | 文件被记事本改动过格式,向教师重新索取原始文件 |
| 查询结果为空 | 库名 / 集合名 / 条件字段拼写不一致(注意大小写) |
7. 环境准备(下一讲:Node.js 与 Express)
下一讲开始编写服务器代码,请在课程开始前逐项完成以下准备,并在群内打卡"Day3 环境打卡":
- 确认
node -v、npm -v均能输出版本号; - 整理项目目录
D:\news:确认src文件夹结构完好(Day 1 的 tmt 页面、system 占位页、css/js/images),并将本讲的schema-demo.js放入D:\news根目录; - 数据自检:启动数据库,在 Compass 中打开 newsList 集合,确认文档数 ≥ 12(被删除的从
news.newsList.json重新导入); - 下次上课的第一件事是启动数据库(
mongod --dbpath D:\mongodb\data),请提前将这条命令默写一遍; - 预习(写入日志,一句话即可):npm 是什么?
npm init -y执行后项目中会多出什么文件? - (可选)安装接口测试工具 Postman 或 Apifox,便于测试接口;未安装也可使用浏览器完成测试;
- 思考题:前端
axios.get("/news")发出的请求,由谁"接听"?接听之后它去哪里获取数据?
8. 学习日志
# 学习日志 Day 2 姓名:____ 日期:____
1. 本讲我学会了:____(3 条以内,写具体的命令)
2. 我遇到的问题与解决:____(什么现象 → 怎么定位 → 怎么解决;未解决也如实记录)
3. 我想进一步弄明白:____
4. 环境准备打卡:已完成 / 未完成(卡在哪一步:____)
9. 本讲小结
- 三层模型:库
news→ 集合newsList→ 文档,_id是每条文档的唯一标识; - CRUD 四命令:
find查、insertOne增、updateOne + $set改、deleteOne删; - Mongoose 三层映射:connect 连库、model 对应集合、方法完成增删改查——将在 Day 3 的服务器代码中逐行兑现。
举手提问