Node.js 操作数据库的三种主要方式

1. 关系型数据库(MySQL/PostgreSQL)

以 MySQL 为例,最常用的是 mysql2 或 sequelize ORM:

方式一:直接使用 mysql2(推荐)

javascript

const mysql = require('mysql2/promise');  // 使用 promise 版本

// 1. 创建连接池
const pool = mysql.createPool({
    host: 'localhost',
    user: 'root',
    password: 'password',
    database: 'myapp',
    waitForConnections: true,
    connectionLimit: 10,
    queueLimit: 0
});

// 2. 使用 async/await 查询(最现代的方式)
async function getUsers() {
    try {
        const [rows, fields] = await pool.query('SELECT * FROM users');
        return rows;
    } catch (error) {
        console.error('数据库查询失败:', error);
    }
}

// 3. 带参数的查询(防止 SQL 注入)
async function getUserById(id) {
    const [rows] = await pool.query('SELECT * FROM users WHERE id = ?', [id]);
    return rows[0];
}

// 4. 插入数据
async function createUser(name, email) {
    const [result] = await pool.query(
        'INSERT INTO users (name, email) VALUES (?, ?)',
        [name, email]
    );
    return result.insertId;  // 返回新插入的ID
}

// 使用示例
app.get('/users', async (req, res) => {
    const users = await getUsers();
    res.json(users);
});

方式二:使用 ORM(Sequelize)- 适合大型项目

javascript

const { Sequelize, DataTypes } = require('sequelize');

// 1. 连接数据库
const sequelize = new Sequelize('database', 'username', 'password', {
    host: 'localhost',
    dialect: 'mysql'
});

// 2. 定义模型(类似 Python 的 Django ORM)
const User = sequelize.define('User', {
    name: {
        type: DataTypes.STRING,
        allowNull: false
    },
    email: {
        type: DataTypes.STRING,
        unique: true,
        validate: {
            isEmail: true
        }
    }
});

// 3. 同步数据库(创建表)
await sequelize.sync();

// 4. 使用 ORM 操作
async function userOperations() {
    // 创建用户
    const user = await User.create({
        name: '张三',
        email: 'zhangsan@example.com'
    });
    
    // 查询用户
    const users = await User.findAll();
    const user2 = await User.findByPk(1);
    const adults = await User.findAll({
        where: { age: { [Op.gte]: 18 } }
    });
    
    // 更新
    await user.update({ name: '李四' });
    
    // 删除
    await user.destroy();
}

2. MongoDB(NoSQL)

MongoDB 是 Node.js 的黄金搭档,常用 mongoose ODM:

javascript

const mongoose = require('mongoose');

// 1. 连接数据库
mongoose.connect('mongodb://localhost:27017/myapp', {
    useNewUrlParser: true,
    useUnifiedTopology: true
});

// 2. 定义 Schema(类似表结构)
const userSchema = new mongoose.Schema({
    name: { type: String, required: true },
    email: { type: String, required: true, unique: true },
    age: Number,
    address: {
        city: String,
        street: String
    },
    tags: [String],  // 数组字段
    createdAt: { type: Date, default: Date.now }
});

// 3. 创建 Model
const User = mongoose.model('User', userSchema);

// 4. 使用 Model 操作数据库
async function mongoOperations() {
    // 创建
    const user = new User({
        name: '王五',
        email: 'wangwu@example.com',
        age: 25,
        address: { city: '北京', street: '长安街' },
        tags: ['程序员', 'Node.js']
    });
    await user.save();
    
    // 查询
    const users = await User.find({ age: { $gt: 18 } });
    const user2 = await User.findOne({ email: 'wangwu@example.com' });
    
    // 更新
    await User.updateOne(
        { name: '王五' },
        { $set: { age: 26 } }
    );
    
    // 删除
    await User.deleteOne({ name: '王五' });
    
    // 复杂查询
    const programmers = await User.find({
        tags: '程序员',
        age: { $gte: 20, $lte: 30 }
    }).sort({ age: -1 }).limit(10);
}

3. Redis(缓存数据库)

javascript

const Redis = require('ioredis');

// 1. 连接 Redis
const redis = new Redis({
    host: 'localhost',
    port: 6379,
    password: 'optional'
});

// 2. 基本操作
async function redisOperations() {
    // 字符串
    await redis.set('key', 'value');
    const value = await redis.get('key');
    
    // 设置过期时间(5秒)
    await redis.setex('session', 5, 'user_data');
    
    // 哈希
    await redis.hset('user:1', 'name', '张三');
    await redis.hset('user:1', 'age', 30);
    const userName = await redis.hget('user:1', 'name');
    
    // 列表
    await redis.lpush('logs', 'error1', 'error2');
    const latestLog = await redis.lpop('logs');
    
    // 自增(用于计数器)
    const views = await redis.incr('page:views');
}

在 Express 中的完整示例

javascript

const express = require('express');
const mysql = require('mysql2/promise');
const app = express();

app.use(express.json());

// 创建数据库连接池
const pool = mysql.createPool({
    host: 'localhost',
    user: 'root',
    password: 'password',
    database: 'myapp'
});

// 获取所有用户
app.get('/api/users', async (req, res) => {
    try {
        const [rows] = await pool.query('SELECT * FROM users');
        res.json(rows);
    } catch (error) {
        res.status(500).json({ error: error.message });
    }
});

// 获取单个用户
app.get('/api/users/:id', async (req, res) => {
    try {
        const [rows] = await pool.query(
            'SELECT * FROM users WHERE id = ?', 
            [req.params.id]
        );
        if (rows.length === 0) {
            return res.status(404).json({ error: '用户不存在' });
        }
        res.json(rows[0]);
    } catch (error) {
        res.status(500).json({ error: error.message });
    }
});

// 创建用户
app.post('/api/users', async (req, res) => {
    const { name, email } = req.body;
    try {
        const [result] = await pool.query(
            'INSERT INTO users (name, email) VALUES (?, ?)',
            [name, email]
        );
        res.status(201).json({ 
            id: result.insertId, 
            name, 
            email 
        });
    } catch (error) {
        res.status(500).json({ error: error.message });
    }
});

// 更新用户
app.put('/api/users/:id', async (req, res) => {
    const { name, email } = req.body;
    try {
        await pool.query(
            'UPDATE users SET name = ?, email = ? WHERE id = ?',
            [name, email, req.params.id]
        );
        res.json({ message: '更新成功' });
    } catch (error) {
        res.status(500).json({ error: error.message });
    }
});

// 删除用户
app.delete('/api/users/:id', async (req, res) => {
    try {
        await pool.query('DELETE FROM users WHERE id = ?', [req.params.id]);
        res.json({ message: '删除成功' });
    } catch (error) {
        res.status(500).json({ error: error.message });
    }
});

app.listen(3000, () => {
    console.log('Server running on port 3000');
});

和其他语言的对比

操作Python (Flask + SQLAlchemy)PHP (Laravel + Eloquent)Node.js (Express + Sequelize)
连接create_engine()DB::connection()new Sequelize()
查询User.query.all()User::all()User.findAll()
插入db.session.add(user)User::create($data)User.create(data)
更新user.name = '新名字'$user->update($data)user.update({name})
删除db.session.delete(user)$user->delete()user.destroy()
事务with db.session.begin():DB::transaction()sequelize.transaction()

关键点总结

  1. 异步是核心:所有数据库操作都是异步的,要用 async/await
  2. 连接池很重要:不要每次请求都创建新连接
  3. 防止 SQL 注入:永远使用参数化查询(? 占位符)
  4. ORM vs 原生 SQL
    • 小项目用原生 SQL 更直接
    • 大项目用 ORM 更好维护
  5. 错误处理:数据库操作一定要用 try-catch

新手推荐路线

  1. 先从 mysql2 的原生 SQL 开始,理解数据库操作
  2. 再用 mongoose 体验 MongoDB 的灵活
  3. 最后用 sequelize ORM 提高效率

发表评论

您的邮箱地址不会被公开。 必填项已用 * 标注

滚动至顶部