在 Node.js 全栈项目中,MongoDB 作为非关系型数据库(NoSQL),常被用于存储结构灵活的文档数据(如用户信息、文章内容、日志等)。以下结合 Node.js 生态(使用官方驱动 或 ODM 工具
mongodb),详解 MongoDB 的基本操作及适配项目的实践。
Mongoose
一、环境准备
安装 MongoDB:本地部署或使用云服务(如 MongoDB Atlas),确保服务启动(默认端口 )。Node.js 依赖:
27017
官方驱动:(适合原生操作)。Mongoose(推荐):
npm install mongodb(基于官方驱动的 ODM 工具,提供 schema 验证、中间件等功能)。
npm install mongoose
二、核心概念(与 SQL 对比)
| MongoDB | SQL | 说明 |
|---|---|---|
| Database | Database | 数据库(独立的存储单元) |
| Collection | Table | 集合(类似表,存储多个文档) |
| Document | Row | 文档(类似行,JSON 格式的数据记录) |
| Field | Column | 字段(文档中的键值对) |
| ObjectId | Primary Key | 文档唯一标识(默认自动生成) |
三、使用 Mongoose 操作 MongoDB(推荐)
Mongoose 是 Node.js 中最流行的 MongoDB ODM 工具,通过 定义数据结构,
Schema 操作集合,简化开发。
Model
1. 连接数据库
// db.js
const mongoose = require('mongoose');
// 连接本地 MongoDB(数据库名:myapp)
mongoose.connect('mongodb://localhost:27017/myapp', {
useNewUrlParser: true,
useUnifiedTopology: true
})
.then(() => console.log('MongoDB 连接成功'))
.catch(err => console.error('连接失败:', err));
module.exports = mongoose;
2. 定义 Schema 与 Model
用于约束文档结构(字段类型、默认值、验证规则等),
Schema 是 Schema 的实例化,对应 MongoDB 的 Collection。
Model
// models/User.js
const mongoose = require('../db');
// 定义用户 Schema
const userSchema = new mongoose.Schema({
username: {
type: String, // 字段类型
required: true, // 必传
unique: true, // 唯一(不可重复)
trim: true // 自动去除首尾空格
},
age: {
type: Number,
min: 0, // 最小值验证
default: 0 // 默认值
},
email: {
type: String,
match: /^[w-]+@([w-]+.)+[w-]+$/, // 邮箱格式验证
required: true
},
createdAt: {
type: Date,
default: Date.now // 默认当前时间
}
});
// 创建 Model(对应集合:users,自动小写并复数化)
const User = mongoose.model('User', userSchema);
module.exports = User;
3. 基本 CRUD 操作
(1)创建文档(Create)
const User = require('./models/User');
// 方式 1:实例化后保存
const user = new User({
username: 'alice',
age: 25,
email: 'alice@example.com'
});
await user.save(); // 返回保存后的文档(含 _id)
// 方式 2:直接通过 Model 创建
const user = await User.create({
username: 'bob',
age: 30,
email: 'bob@example.com'
});
(2)查询文档(Read)
// 1. 查询所有文档
const allUsers = await User.find(); // 返回数组
// 2. 条件查询(年龄 > 20)
const adults = await User.find({ age: { $gt: 20 } });
// 3. 投影(只返回 username 和 email,不返回 _id)
const userFields = await User.find({}, { username: 1, email: 1, _id: 0 });
// 4. 排序(按 age 升序,-1 为降序)
const sortedUsers = await User.find().sort({ age: 1 });
// 5. 分页(跳过前 10 条,取 5 条)
const paginatedUsers = await User.find().skip(10).limit(5);
// 6. 查询单个文档(按条件,返回第一个)
const user = await User.findOne({ username: 'alice' });
// 7. 按 ID 查询
const user = await User.findById('6555a7b3f2d4e8c3d8f7e6d5');
(3)更新文档(Update)
// 1. 更新单个文档(按条件,返回更新后的文档)
const updatedUser = await User.findOneAndUpdate(
{ username: 'alice' }, // 条件
{ age: 26 }, // 更新内容
{ new: true } // 选项:返回更新后的数据(默认返回更新前)
);
// 2. 更新多个文档(年龄 < 18 的设为 18)
const result = await User.updateMany(
{ age: { $lt: 18 } },
{ age: 18 }
);
// result 包含:n(匹配数量)、nModified(修改数量)等
// 3. 按 ID 更新
const updatedUser = await User.findByIdAndUpdate(
'6555a7b3f2d4e8c3d8f7e6d5',
{ email: 'new-alice@example.com' },
{ new: true }
);
(4)删除文档(Delete)
// 1. 删除单个文档(按条件)
const deletedUser = await User.findOneAndDelete({ username: 'bob' });
// 2. 删除多个文档(年龄 > 50)
const result = await User.deleteMany({ age: { $gt: 50 } });
// 3. 按 ID 删除
const deletedUser = await User.findByIdAndDelete('6555a7b3f2d4e8c3d8f7e6d5');
4. 高级查询(条件操作符)
MongoDB 提供丰富的查询操作符,满足复杂条件查询:
| 操作符 | 说明 | 示例(查询条件) |
|---|---|---|
|
等于 | |
|
不等于 | |
/ |
大于 / 小于 | |
|
在数组中 | |
|
正则匹配 | |
/ |
逻辑与 / 或 | |
四、使用官方驱动
mongodb 操作(原生方式)
mongodb
若需更灵活的原生操作,可直接使用 驱动:
mongodb
const { MongoClient } = require('mongodb');
// 连接客户端
const client = new MongoClient('mongodb://localhost:27017');
await client.connect();
// 获取数据库和集合
const db = client.db('myapp');
const usersCollection = db.collection('users');
// 1. 创建文档
await usersCollection.insertOne({ username: 'carol', age: 28 });
// 2. 查询文档
const user = await usersCollection.findOne({ username: 'carol' });
// 3. 更新文档
await usersCollection.updateOne(
{ username: 'carol' },
{ $set: { age: 29 } }
);
// 4. 删除文档
await usersCollection.deleteOne({ username: 'carol' });
// 关闭连接
await client.close();
五、适配 Node.js 全栈项目的实践建议
分层设计:
模型层():定义 Mongoose Schema 和 Model。服务层(
models):封装数据库操作逻辑(如
services)。控制器层(
userService.getById()):处理 HTTP 请求,调用服务层方法返回结果。
controllers
// services/userService.js
const User = require('../models/User');
exports.getUserById = async (id) => {
return await User.findById(id);
};
// controllers/userController.js
const userService = require('../services/userService');
exports.getUser = async (req, res) => {
const user = await userService.getUserById(req.params.id);
res.json(user);
};
错误处理:
捕获数据库操作错误(如重复键、验证失败),返回友好的 HTTP 错误:
try {
await User.create({ username: 'alice', email: 'invalid-email' });
} catch (err) {
if (err.code === 11000) { // 重复键错误
return res.status(400).json({ error: '用户名已存在' });
}
if (err.name === 'ValidationError') { // 验证错误
return res.status(400).json({ error: err.message });
}
}
索引优化:
对高频查询字段创建索引(如 、
username),提升查询性能:
email
// 在 Schema 中定义索引
userSchema.index({ username: 1 }); // 1 为升序索引
userSchema.index({ email: 1 });
批量操作:
对大量数据使用批量插入/更新(、
insertMany),减少数据库交互次数:
bulkWrite
// 批量插入
await User.insertMany([
{ username: 'user1', email: 'user1@test.com' },
{ username: 'user2', email: 'user2@test.com' }
]);
总结
MongoDB 在 Node.js 项目中通过 Mongoose 可简化操作,核心是通过 约束数据、
Schema 执行 CRUD。适配全栈项目时,需注意分层设计、错误处理和性能优化(如索引、批量操作)。对于结构灵活、迭代快速的项目(如社交应用、内容管理系统),MongoDB 是高效的选择。
Model

