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 -vnpm -vmongod --version 均应能输出版本号,Compass 已安装,D:\mongodb\data 文件夹已创建——本讲第 2 节将立即用到这些准备。

资源下载

  • 新闻数据文件:news.newsList.json(由教师统一发放)

1. 数据库基础概念

1.1 为什么需要数据库

Day 1 页面中的新闻是写死在 HTML 里的假数据(非动态更新的),存在三个无法回避的问题:

  1. 修改一条新闻就要修改代码,修改后还需重新发布页面;
  2. 数据量大时(例如数万条新闻),页面文件无法管理;
  3. 前台展示页与后台管理系统是两套页面,数据无法共享。

数据库(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 集合

  1. 点击 Create Database
  2. Database Name 填写 news,Collection Name 填写 newsList(一步同时创建库和第一个集合);
  3. 点击 Create Database 完成创建。

注意:两个名称必须与 1.3 节表格完全一致。名称错误时程序不会报错,但 Day 3 的代码将连接到一个空库,查询不到任何数据。

3.3 导入新闻数据

  1. 进入 newsList 集合页面,点击 ADD DATA → Import JSON
  2. 选择 news.newsList.json → Import;
  3. 通过表格视图 / JSON 视图切换按钮,分别查看两种数据展示方式。

3.4 验证导入结果

  • 文档数量 ≥ 12 条;
  • 随机打开一条文档,确认 titleauthordateimgSrc_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 不可省略。不带 $setupdateOne 会用新对象整条覆盖旧文档,其余字段全部丢失。动手验证:故意执行一次不带 $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 包尚未安装——安装是下一讲的第一项操作。请核对代码中的 newsnewsList 与 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 环境打卡":

  1. 确认 node -vnpm -v 均能输出版本号;
  2. 整理项目目录 D:\news:确认 src 文件夹结构完好(Day 1 的 tmt 页面、system 占位页、css/js/images),并将本讲的 schema-demo.js 放入 D:\news 根目录;
  3. 数据自检:启动数据库,在 Compass 中打开 newsList 集合,确认文档数 ≥ 12(被删除的从 news.newsList.json 重新导入);
  4. 下次上课的第一件事是启动数据库mongod --dbpath D:\mongodb\data),请提前将这条命令默写一遍;
  5. 预习(写入日志,一句话即可):npm 是什么?npm init -y 执行后项目中会多出什么文件?
  6. (可选)安装接口测试工具 Postman 或 Apifox,便于测试接口;未安装也可使用浏览器完成测试;
  7. 思考题:前端 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 的服务器代码中逐行兑现。