Search K
Appearance
Appearance
📊 SEO元描述:2024年最新Node.js数据库操作教程,详解MongoDB集成、MySQL连接、Mongoose ORM、Sequelize使用。包含完整CRUD操作实战,适合全栈开发者快速掌握数据库开发。
核心关键词:Node.js数据库操作2024、MongoDB Node.js集成、MySQL Node.js连接、Mongoose ORM教程、Sequelize使用指南
长尾关键词:Node.js怎么连接数据库、MongoDB和Node.js怎么集成、MySQL Node.js操作教程、ORM是什么、Node.js数据库最佳实践
通过本节Node.js数据库操作教程,你将系统性掌握:
Node.js项目如何选择数据库?这是后端开发的核心决策问题。数据库选择直接影响应用架构设计和开发效率,也是现代Web应用的重要技术选型。
💡 选择原则:根据数据结构复杂度、查询需求、扩展性要求和团队技术栈来选择合适的数据库
// 🎉 MongoDB连接配置示例
const mongoose = require('mongoose');
// 数据库连接配置
const connectDB = async () => {
try {
const conn = await mongoose.connect(process.env.MONGODB_URI || 'mongodb://localhost:27017/myapp', {
useNewUrlParser: true,
useUnifiedTopology: true,
});
console.log(`MongoDB连接成功: ${conn.connection.host}`);
} catch (error) {
console.error('MongoDB连接失败:', error.message);
process.exit(1);
}
};
// 连接事件监听
mongoose.connection.on('connected', () => {
console.log('Mongoose连接到MongoDB');
});
mongoose.connection.on('error', (err) => {
console.error('Mongoose连接错误:', err);
});
mongoose.connection.on('disconnected', () => {
console.log('Mongoose断开连接');
});
module.exports = connectDB;// 🎉 Mongoose模型定义示例
const mongoose = require('mongoose');
const bcrypt = require('bcryptjs');
// 用户模型Schema
const userSchema = new mongoose.Schema({
name: {
type: String,
required: [true, '用户名不能为空'],
trim: true,
maxlength: [50, '用户名不能超过50个字符']
},
email: {
type: String,
required: [true, '邮箱不能为空'],
unique: true,
lowercase: true,
match: [/^\w+([.-]?\w+)*@\w+([.-]?\w+)*(\.\w{2,3})+$/, '请输入有效的邮箱地址']
},
password: {
type: String,
required: [true, '密码不能为空'],
minlength: [6, '密码至少6个字符'],
select: false // 查询时默认不返回密码字段
},
avatar: {
type: String,
default: 'default-avatar.jpg'
},
role: {
type: String,
enum: ['user', 'admin'],
default: 'user'
},
isActive: {
type: Boolean,
default: true
},
lastLogin: {
type: Date
}
}, {
timestamps: true, // 自动添加createdAt和updatedAt字段
toJSON: { virtuals: true },
toObject: { virtuals: true }
});
// 虚拟字段
userSchema.virtual('fullName').get(function() {
return `${this.firstName} ${this.lastName}`;
});
// 中间件:保存前加密密码
userSchema.pre('save', async function(next) {
if (!this.isModified('password')) return next();
this.password = await bcrypt.hash(this.password, 12);
next();
});
// 实例方法:验证密码
userSchema.methods.comparePassword = async function(candidatePassword) {
return await bcrypt.compare(candidatePassword, this.password);
};
// 静态方法:查找活跃用户
userSchema.statics.findActiveUsers = function() {
return this.find({ isActive: true });
};
const User = mongoose.model('User', userSchema);
module.exports = User;// 🎉 MongoDB CRUD操作示例
const User = require('../models/User');
// 用户控制器
const userController = {
// 创建用户
createUser: async (req, res) => {
try {
const { name, email, password } = req.body;
// 检查用户是否已存在
const existingUser = await User.findOne({ email });
if (existingUser) {
return res.status(400).json({
success: false,
message: '该邮箱已被注册'
});
}
// 创建新用户
const user = await User.create({
name,
email,
password
});
res.status(201).json({
success: true,
data: {
id: user._id,
name: user.name,
email: user.email,
createdAt: user.createdAt
},
message: '用户创建成功'
});
} catch (error) {
res.status(500).json({
success: false,
message: '创建用户失败',
error: error.message
});
}
},
// 获取用户列表
getUsers: async (req, res) => {
try {
const { page = 1, limit = 10, search, role } = req.query;
// 构建查询条件
const query = {};
if (search) {
query.$or = [
{ name: { $regex: search, $options: 'i' } },
{ email: { $regex: search, $options: 'i' } }
];
}
if (role) {
query.role = role;
}
// 分页查询
const users = await User.find(query)
.select('-password')
.sort({ createdAt: -1 })
.limit(limit * 1)
.skip((page - 1) * limit);
const total = await User.countDocuments(query);
res.json({
success: true,
data: users,
pagination: {
page: parseInt(page),
limit: parseInt(limit),
total,
pages: Math.ceil(total / limit)
}
});
} catch (error) {
res.status(500).json({
success: false,
message: '获取用户列表失败',
error: error.message
});
}
},
// 更新用户
updateUser: async (req, res) => {
try {
const { id } = req.params;
const updates = req.body;
// 不允许直接更新密码
delete updates.password;
const user = await User.findByIdAndUpdate(
id,
updates,
{ new: true, runValidators: true }
).select('-password');
if (!user) {
return res.status(404).json({
success: false,
message: '用户不存在'
});
}
res.json({
success: true,
data: user,
message: '用户信息更新成功'
});
} catch (error) {
res.status(500).json({
success: false,
message: '更新用户失败',
error: error.message
});
}
},
// 删除用户
deleteUser: async (req, res) => {
try {
const { id } = req.params;
const user = await User.findByIdAndDelete(id);
if (!user) {
return res.status(404).json({
success: false,
message: '用户不存在'
});
}
res.json({
success: true,
message: '用户删除成功'
});
} catch (error) {
res.status(500).json({
success: false,
message: '删除用户失败',
error: error.message
});
}
}
};
module.exports = userController;MongoDB的优势特点:
// 🎉 MySQL连接配置示例
const { Sequelize } = require('sequelize');
// 数据库连接配置
const sequelize = new Sequelize(
process.env.DB_NAME || 'myapp',
process.env.DB_USER || 'root',
process.env.DB_PASS || 'password',
{
host: process.env.DB_HOST || 'localhost',
port: process.env.DB_PORT || 3306,
dialect: 'mysql',
logging: process.env.NODE_ENV === 'development' ? console.log : false,
pool: {
max: 10,
min: 0,
acquire: 30000,
idle: 10000
},
define: {
timestamps: true,
underscored: true,
freezeTableName: true
}
}
);
// 测试数据库连接
const testConnection = async () => {
try {
await sequelize.authenticate();
console.log('MySQL数据库连接成功');
} catch (error) {
console.error('MySQL数据库连接失败:', error);
}
};
module.exports = { sequelize, testConnection };// 🎉 Sequelize模型定义示例
const { DataTypes } = require('sequelize');
const { sequelize } = require('../config/database');
const bcrypt = require('bcryptjs');
// 用户模型定义
const User = sequelize.define('User', {
id: {
type: DataTypes.INTEGER,
primaryKey: true,
autoIncrement: true
},
name: {
type: DataTypes.STRING(50),
allowNull: false,
validate: {
notEmpty: {
msg: '用户名不能为空'
},
len: {
args: [2, 50],
msg: '用户名长度必须在2-50个字符之间'
}
}
},
email: {
type: DataTypes.STRING(100),
allowNull: false,
unique: {
msg: '该邮箱已被注册'
},
validate: {
isEmail: {
msg: '请输入有效的邮箱地址'
}
}
},
password: {
type: DataTypes.STRING(255),
allowNull: false,
validate: {
len: {
args: [6, 255],
msg: '密码长度至少6个字符'
}
}
},
avatar: {
type: DataTypes.STRING(255),
defaultValue: 'default-avatar.jpg'
},
role: {
type: DataTypes.ENUM('user', 'admin'),
defaultValue: 'user'
},
isActive: {
type: DataTypes.BOOLEAN,
defaultValue: true
},
lastLogin: {
type: DataTypes.DATE
}
}, {
tableName: 'users',
hooks: {
// 保存前加密密码
beforeCreate: async (user) => {
if (user.password) {
user.password = await bcrypt.hash(user.password, 12);
}
},
beforeUpdate: async (user) => {
if (user.changed('password')) {
user.password = await bcrypt.hash(user.password, 12);
}
}
}
});
// 实例方法:验证密码
User.prototype.comparePassword = async function(candidatePassword) {
return await bcrypt.compare(candidatePassword, this.password);
};
// 类方法:查找活跃用户
User.findActiveUsers = function() {
return this.findAll({
where: { isActive: true }
});
};
module.exports = User;MySQL vs MongoDB对比:
| 特性 | MongoDB | MySQL |
|---|---|---|
| 数据模型 | 文档型 | 关系型 |
| Schema | 灵活 | 固定 |
| 查询语言 | MongoDB Query | SQL |
| 事务支持 | 有限支持 | 完整支持 |
| 扩展性 | 水平扩展 | 垂直扩展 |
| 学习成本 | 较低 | 较高 |
💼 选择建议:快速原型和灵活数据结构选MongoDB;复杂业务逻辑和强一致性要求选MySQL
通过本节Node.js数据库操作教程的学习,你已经掌握:
A: 如果数据结构灵活、需要快速迭代,选择MongoDB;如果业务逻辑复杂、需要强一致性和复杂关联查询,选择MySQL。也可以混合使用。
A: ORM会有一定性能开销,但带来的开发效率提升通常值得。对于性能敏感的查询,可以使用原生SQL或聚合管道。
A: Mongoose和Sequelize都内置连接池管理。可以通过配置参数调整连接池大小,监控连接使用情况,避免连接泄漏。
A: 使用迁移工具如Sequelize migrations或MongoDB的迁移脚本。版本控制迁移文件,确保开发、测试、生产环境数据结构一致。
A: 使用参数化查询防止SQL注入,对敏感数据加密存储,实施访问控制,定期备份数据,监控异常操作。
// 问题:如何优化数据库查询性能?
// 解决:使用索引、分页、字段选择等优化技术
// MongoDB查询优化
const getOptimizedUsers = async (req, res) => {
try {
const { page = 1, limit = 10 } = req.query;
// 使用索引字段查询
const users = await User.find({ isActive: true })
.select('name email avatar createdAt') // 只选择需要的字段
.sort({ createdAt: -1 }) // 确保createdAt字段有索引
.limit(limit * 1)
.skip((page - 1) * limit)
.lean(); // 返回普通JavaScript对象,提升性能
res.json({ success: true, data: users });
} catch (error) {
res.status(500).json({ success: false, error: error.message });
}
};
// MySQL查询优化
const getOptimizedProducts = async (req, res) => {
try {
const products = await Product.findAll({
attributes: ['id', 'name', 'price'], // 只选择需要的字段
where: {
isActive: true,
price: { [Op.gte]: 100 } // 使用索引字段过滤
},
include: [{
model: Category,
attributes: ['name'],
required: true // INNER JOIN而不是LEFT JOIN
}],
order: [['createdAt', 'DESC']],
limit: 20
});
res.json({ success: true, data: products });
} catch (error) {
res.status(500).json({ success: false, error: error.message });
}
};// 问题:如何集成Redis缓存提升数据库性能?
// 解决:在数据库操作中集成Redis缓存层
const redis = require('redis');
const client = redis.createClient();
const getCachedUser = async (userId) => {
try {
// 先从缓存获取
const cachedUser = await client.get(`user:${userId}`);
if (cachedUser) {
return JSON.parse(cachedUser);
}
// 缓存未命中,从数据库获取
const user = await User.findById(userId).select('-password');
if (user) {
// 存入缓存,设置过期时间
await client.setex(`user:${userId}`, 3600, JSON.stringify(user));
}
return user;
} catch (error) {
console.error('获取用户失败:', error);
throw error;
}
};"数据库是现代Web应用的核心基础设施。通过掌握MongoDB和MySQL的集成使用,你已经具备了构建数据驱动应用的完整能力。恭喜你完成了Node.js后端开发的学习!"