一、MySQL 数据库操作

1.1 安装 mysql2 驱动

1
npm install mysql2

1.2 创建连接

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
// db/mysql.js
const mysql = require('mysql2');

// 创建连接
const connection = mysql.createConnection({
host: 'localhost',
user: 'root',
password: 'your_password',
database: 'myapp'
});

// 连接数据库
connection.connect((err) => {
if (err) {
console.error('数据库连接失败:', err.message);
return;
}
console.log('数据库连接成功');
});

// 导出连接对象
module.exports = connection;

1.3 基本查询(回调方式)

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
const connection = require('./db/mysql');

// 查询所有用户
connection.query('SELECT * FROM users', (err, results, fields) => {
if (err) {
console.error('查询失败:', err.message);
return;
}
console.log('查询结果:', results);
console.log('字段信息:', fields);
});

// 带参数查询(防止 SQL 注入)
const userId = 1;
connection.query(
'SELECT * FROM users WHERE id = ?',
[userId],
(err, results) => {
if (err) throw err;
console.log(results);
}
);

// 插入数据
const newUser = { name: '张三', email: 'zhangsan@example.com', age: 25 };
connection.query(
'INSERT INTO users SET ?',
newUser,
(err, result) => {
if (err) throw err;
console.log('插入 ID:', result.insertId);
}
);

// 更新数据
connection.query(
'UPDATE users SET age = ? WHERE id = ?',
[26, 1],
(err, result) => {
if (err) throw err;
console.log('影响行数:', result.affectedRows);
}
);

// 删除数据
connection.query(
'DELETE FROM users WHERE id = ?',
[1],
(err, result) => {
if (err) throw err;
console.log('删除行数:', result.affectedRows);
}
);

// 关闭连接
connection.end();

1.4 Promise 方式查询

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
// db/mysql-promise.js
const mysql = require('mysql2/promise');

async function main() {
// 创建连接
const connection = await mysql.createConnection({
host: 'localhost',
user: 'root',
password: 'your_password',
database: 'myapp'
});

try {
// 查询
const [rows] = await connection.execute('SELECT * FROM users');
console.log(rows);

// 插入
const [result] = await connection.execute(
'INSERT INTO users (name, email, age) VALUES (?, ?, ?)',
['李四', 'lisi@example.com', 30]
);
console.log('插入 ID:', result.insertId);

// 更新
const [updateResult] = await connection.execute(
'UPDATE users SET age = ? WHERE id = ?',
[31, 2]
);
console.log('更新行数:', updateResult.affectedRows);

// 删除
const [deleteResult] = await connection.execute(
'DELETE FROM users WHERE id = ?',
[2]
);
console.log('删除行数:', deleteResult.affectedRows);

} finally {
await connection.end();
}
}

main().catch(console.error);

1.5 连接池

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// db/pool.js
const mysql = require('mysql2');

const pool = mysql.createPool({
host: 'localhost',
user: 'root',
password: 'your_password',
database: 'myapp',
waitForConnections: true,
connectionLimit: 10, // 连接池大小
queueLimit: 0 // 排队限制(0表示无限制)
});

// 导出 Promise 版本的连接池
module.exports = pool.promise();

使用连接池:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
const db = require('./db/pool');

async function getUsers() {
const [rows] = await db.execute('SELECT * FROM users');
return rows;
}

async function createUser(name, email, age) {
const [result] = await db.execute(
'INSERT INTO users (name, email, age) VALUES (?, ?, ?)',
[name, email, age]
);
return result.insertId;
}

module.exports = { getUsers, createUser };

1.6 事务处理

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
const db = require('./db/pool');

async function transferMoney(fromId, toId, amount) {
const connection = await db.getConnection();

try {
// 开始事务
await connection.beginTransaction();

// 查询转出账户余额
const [fromRows] = await connection.execute(
'SELECT balance FROM accounts WHERE id = ?',
[fromId]
);

if (fromRows.length === 0) {
throw new Error('转出账户不存在');
}

const fromBalance = fromRows[0].balance;
if (fromBalance < amount) {
throw new Error('余额不足');
}

// 扣除转出账户金额
await connection.execute(
'UPDATE accounts SET balance = balance - ? WHERE id = ?',
[amount, fromId]
);

// 增加转入账户金额
await connection.execute(
'UPDATE accounts SET balance = balance + ? WHERE id = ?',
[amount, toId]
);

// 提交事务
await connection.commit();
console.log('转账成功');

} catch (error) {
// 回滚事务
await connection.rollback();
console.error('转账失败:', error.message);
throw error;
} finally {
connection.release(); // 释放连接回连接池
}
}

二、MongoDB 数据库操作

2.1 安装 mongodb 驱动

1
npm install mongodb

2.2 创建连接

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
// db/mongo.js
const { MongoClient } = require('mongodb');

const uri = 'mongodb://localhost:27017';
const client = new MongoClient(uri);

let database;

async function connect() {
try {
await client.connect();
console.log('MongoDB 连接成功');
database = client.db('myapp');
return database;
} catch (error) {
console.error('MongoDB 连接失败:', error.message);
throw error;
}
}

function getDb() {
return database;
}

module.exports = { connect, getDb };

2.3 文档 CRUD 操作

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
const { connect, getDb } = require('./db/mongo');

async function main() {
await connect();
const db = getDb();
const users = db.collection('users');

// 插入单个文档
const insertResult = await users.insertOne({
name: '张三',
email: 'zhangsan@example.com',
age: 25,
createdAt: new Date()
});
console.log('插入 ID:', insertResult.insertedId);

// 插入多个文档
const insertManyResult = await users.insertMany([
{ name: '李四', email: 'lisi@example.com', age: 30 },
{ name: '王五', email: 'wangwu@example.com', age: 28 }
]);
console.log('插入数量:', insertManyResult.insertedCount);

// 查询所有文档
const allUsers = await users.find({}).toArray();
console.log('所有用户:', allUsers);

// 条件查询
const user = await users.findOne({ name: '张三' });
console.log('查询结果:', user);

// 查询多个文档
const youngUsers = await users.find({ age: { $lt: 30 } }).toArray();
console.log('年龄小于30的用户:', youngUsers);

// 更新单个文档
const updateResult = await users.updateOne(
{ name: '张三' },
{ $set: { age: 26 } }
);
console.log('更新行数:', updateResult.modifiedCount);

// 更新多个文档
const updateManyResult = await users.updateMany(
{ age: { $lt: 30 } },
{ $set: { status: 'young' } }
);
console.log('更新行数:', updateManyResult.modifiedCount);

// 删除单个文档
const deleteResult = await users.deleteOne({ name: '张三' });
console.log('删除行数:', deleteResult.deletedCount);

// 删除多个文档
const deleteManyResult = await users.deleteMany({ status: 'young' });
console.log('删除行数:', deleteManyResult.deletedCount);
}

main().catch(console.error);

2.4 聚合查询

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
const { connect, getDb } = require('./db/mongo');

async function aggregateDemo() {
await connect();
const db = getDb();
const orders = db.collection('orders');

// 按用户分组统计订单总额
const result = await orders.aggregate([
{ $match: { status: 'completed' } }, // 筛选已完成订单
{ $group: { _id: '$userId', total: { $sum: '$amount' } } }, // 按用户分组求和
{ $sort: { total: -1 } }, // 按总额降序排序
{ $limit: 10 } // 取前10名
]).toArray();

console.log('用户消费排行:', result);
}

aggregateDemo().catch(console.error);

三、Redis 缓存操作

3.1 安装 ioredis

1
npm install ioredis

3.2 创建连接

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
// db/redis.js
const Redis = require('ioredis');

const redis = new Redis({
host: 'localhost',
port: 6379,
password: '', // 如果有密码
db: 0 // 数据库编号
});

redis.on('connect', () => {
console.log('Redis 连接成功');
});

redis.on('error', (err) => {
console.error('Redis 错误:', err.message);
});

module.exports = redis;

3.3 字符串操作

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
const redis = require('./db/redis');

async function stringDemo() {
// 设置值
await redis.set('name', '张三');
await redis.set('age', '25');
await redis.set('token', 'abc123', 'EX', 3600); // 设置并指定过期时间(秒)

// 获取值
const name = await redis.get('name');
console.log('name:', name);

// 自增
await redis.incr('counter');
await redis.incrby('counter', 10);

// 获取剩余过期时间(秒)
const ttl = await redis.ttl('token');
console.log('token 剩余时间:', ttl, '秒');

// 删除键
await redis.del('name');
}

stringDemo().catch(console.error);

3.4 哈希操作

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
const redis = require('./db/redis');

async function hashDemo() {
// 设置哈希字段
await redis.hset('user:1', 'name', '张三');
await redis.hset('user:1', 'email', 'zhangsan@example.com');
await redis.hset('user:1', 'age', 25);

// 一次设置多个字段
await redis.hmset('user:2', {
name: '李四',
email: 'lisi@example.com',
age: 30
});

// 获取单个字段
const name = await redis.hget('user:1', 'name');
console.log('name:', name);

// 获取所有字段
const user = await redis.hgetall('user:1');
console.log('user:', user);

// 判断字段是否存在
const exists = await redis.hexists('user:1', 'name');
console.log('name 字段存在:', exists);

// 删除字段
await redis.hdel('user:1', 'age');

// 自增字段
await redis.hincrby('user:1', 'age', 1);
}

hashDemo().catch(console.error);

3.5 列表操作

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
const redis = require('./db/redis');

async function listDemo() {
// 左侧插入
await redis.lpush('queue', 'task1', 'task2', 'task3');

// 右侧插入
await redis.rpush('queue', 'task4');

// 获取列表长度
const length = await redis.llen('queue');
console.log('队列长度:', length);

// 获取列表元素
const items = await redis.lrange('queue', 0, -1); // 获取所有元素
console.log('队列内容:', items);

// 左侧弹出
const leftItem = await redis.lpop('queue');
console.log('左侧弹出:', leftItem);

// 右侧弹出
const rightItem = await redis.rpop('queue');
console.log('右侧弹出:', rightItem);
}

listDemo().catch(console.error);

3.6 发布订阅

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
const Redis = require('ioredis');
const publisher = new Redis();
const subscriber = new Redis();

// 订阅频道
subscriber.subscribe('news', 'weather', (err, count) => {
if (err) {
console.error('订阅失败:', err.message);
return;
}
console.log(`当前订阅了 ${count} 个频道`);
});

// 监听消息
subscriber.on('message', (channel, message) => {
console.log(`收到消息 [${channel}]: ${message}`);
});

// 发布消息
setTimeout(() => {
publisher.publish('news', '今日头条:Node.js 教程更新');
publisher.publish('weather', '今日天气:晴,25℃');
}, 1000);

四、ORM 框架

4.1 Sequelize(MySQL ORM)

安装

1
npm install sequelize mysql2

数据库连接

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
// db/sequelize.js
const { Sequelize } = require('sequelize');

const sequelize = new Sequelize('myapp', 'root', 'your_password', {
host: 'localhost',
dialect: 'mysql',
logging: false, // 关闭日志
pool: {
max: 5,
min: 0,
acquire: 30000,
idle: 10000
}
});

// 测试连接
async function testConnection() {
try {
await sequelize.authenticate();
console.log('数据库连接成功');
} catch (error) {
console.error('数据库连接失败:', error.message);
}
}

testConnection();

module.exports = sequelize;

定义模型

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
// models/User.js
const { DataTypes } = require('sequelize');
const sequelize = require('../db/sequelize');

const User = sequelize.define('User', {
id: {
type: DataTypes.INTEGER,
primaryKey: true,
autoIncrement: true
},
name: {
type: DataTypes.STRING(50),
allowNull: false,
validate: {
notEmpty: true
}
},
email: {
type: DataTypes.STRING(100),
allowNull: false,
unique: true,
validate: {
isEmail: true
}
},
age: {
type: DataTypes.INTEGER,
defaultValue: 18,
validate: {
min: 0,
max: 120
}
},
status: {
type: DataTypes.ENUM('active', 'inactive'),
defaultValue: 'active'
}
}, {
tableName: 'users',
timestamps: true, // 自动添加 createdAt 和 updatedAt
paranoid: true // 软删除(添加 deletedAt)
});

module.exports = User;

CRUD 操作

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
const User = require('./models/User');

// 创建用户
async function createUser() {
const user = await User.create({
name: '张三',
email: 'zhangsan@example.com',
age: 25
});
console.log('创建成功:', user.id);
}

// 查询所有用户
async function findAllUsers() {
const users = await User.findAll({
attributes: ['id', 'name', 'email'],
where: { status: 'active' },
order: [['createdAt', 'DESC']],
limit: 10
});
console.log(users);
}

// 查询单个用户
async function findUserById(id) {
const user = await User.findByPk(id);
if (!user) {
console.log('用户不存在');
return;
}
console.log(user);
}

// 更新用户
async function updateUser(id, newData) {
const result = await User.update(newData, {
where: { id }
});
console.log('更新行数:', result[0]);
}

// 删除用户(软删除)
async function deleteUser(id) {
const result = await User.destroy({
where: { id }
});
console.log('删除行数:', result);
}

// 真正删除
async function forceDeleteUser(id) {
const result = await User.destroy({
where: { id },
force: true
});
console.log('删除行数:', result);
}

4.2 Mongoose(MongoDB ODM)

安装

1
npm install mongoose

数据库连接

1
2
3
4
5
6
7
8
// db/mongoose.js
const mongoose = require('mongoose');

mongoose.connect('mongodb://localhost:27017/myapp')
.then(() => console.log('MongoDB 连接成功'))
.catch(err => console.error('MongoDB 连接失败:', err.message));

module.exports = mongoose;

定义模型

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
// models/User.js
const mongoose = require('mongoose');

const userSchema = new mongoose.Schema({
name: {
type: String,
required: [true, '姓名不能为空'],
trim: true,
maxlength: 50
},
email: {
type: String,
required: true,
unique: true,
match: [/^\S+@\S+\.\S+$/, '邮箱格式不正确']
},
age: {
type: Number,
default: 18,
min: 0,
max: 120
},
role: {
type: String,
enum: ['user', 'admin'],
default: 'user'
}
}, {
timestamps: true, // 自动添加 createdAt 和 updatedAt
versionKey: false // 不添加 __v 字段
});

// 实例方法
userSchema.methods.getDisplayName = function() {
return `${this.name} (${this.email})`;
};

// 静态方法
userSchema.statics.findByEmail = function(email) {
return this.findOne({ email });
};

// 中间件(保存前执行)
userSchema.pre('save', function(next) {
console.log('保存前:', this);
next();
});

const User = mongoose.model('User', userSchema);

module.exports = User;

CRUD 操作

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
const User = require('./models/User');

// 创建用户
async function createUser() {
const user = await User.create({
name: '张三',
email: 'zhangsan@example.com',
age: 25
});
console.log('创建成功:', user.id);
}

// 查询所有用户
async function findAllUsers() {
const users = await User.find()
.select('name email age')
.where('role').equals('user')
.sort('-createdAt')
.limit(10);
console.log(users);
}

// 查询单个用户
async function findUserById(id) {
const user = await User.findById(id);
if (!user) {
console.log('用户不存在');
return;
}
console.log(user);
}

// 使用静态方法
async function findByEmail(email) {
const user = await User.findByEmail(email);
console.log(user);
}

// 更新用户
async function updateUser(id, newData) {
const user = await User.findByIdAndUpdate(
id,
newData,
{ new: true, runValidators: true }
);
console.log(user);
}

// 删除用户
async function deleteUser(id) {
await User.findByIdAndDelete(id);
console.log('删除成功');
}

五、实战练习:博客系统 API

5.1 项目结构

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
blog-api/
├── config/
│ └── database.js
├── models/
│ ├── User.js
│ ├── Post.js
│ └── Comment.js
├── controllers/
│ ├── userController.js
│ ├── postController.js
│ └── commentController.js
├── routes/
│ ├── users.js
│ ├── posts.js
│ └── comments.js
├── middleware/
│ └── auth.js
├── app.js
└── package.json

5.2 数据库配置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// config/database.js
const { Sequelize } = require('sequelize');

const sequelize = new Sequelize(
process.env.DB_NAME || 'blog',
process.env.DB_USER || 'root',
process.env.DB_PASSWORD || '',
{
host: process.env.DB_HOST || 'localhost',
dialect: 'mysql',
logging: false
}
);

module.exports = sequelize;

5.3 定义模型关联

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
// models/User.js
const { DataTypes } = require('sequelize');
const sequelize = require('../config/database');

const User = sequelize.define('User', {
username: {
type: DataTypes.STRING(50),
allowNull: false,
unique: true
},
email: {
type: DataTypes.STRING(100),
allowNull: false,
unique: true
},
password: {
type: DataTypes.STRING(255),
allowNull: false
}
});

module.exports = User;

// models/Post.js
const { DataTypes } = require('sequelize');
const sequelize = require('../config/database');

const Post = sequelize.define('Post', {
title: {
type: DataTypes.STRING(200),
allowNull: false
},
content: {
type: DataTypes.TEXT,
allowNull: false
},
status: {
type: DataTypes.ENUM('draft', 'published'),
defaultValue: 'draft'
}
});

module.exports = Post;

// models/index.js
const sequelize = require('../config/database');
const User = require('./User');
const Post = require('./Post');

// 定义关联关系
User.hasMany(Post, { foreignKey: 'authorId', as: 'posts' });
Post.belongsTo(User, { foreignKey: 'authorId', as: 'author' });

module.exports = { sequelize, User, Post };

💡 小结:掌握数据库操作是后端开发的核心能力。MySQL 适合结构化数据和复杂查询,MongoDB 适合灵活的文档存储,Redis 适合缓存和会话管理。ORM 框架能大幅提升开发效率,但也要注意性能优化和查询优化。