Skip to content

Node.js 数据库操作实践

数据库选择

Node.js 支持多种数据库,常见的有:

  • MongoDB:NoSQL 文档数据库
  • MySQL/PostgreSQL:关系型数据库
  • Redis:内存键值数据库

MongoDB 操作

安装和连接

bash
npm install mongodb
javascript
const { MongoClient } = require('mongodb');

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

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

基本 CRUD 操作

javascript
async function crudOperations() {
  const db = await connect();
  const collection = db.collection('users');
  
  // 创建(Create)
  const insertResult = await collection.insertOne({
    name: 'John',
    email: 'john@example.com',
    age: 30
  });
  console.log('插入文档 ID:', insertResult.insertedId);
  
  // 插入多个文档
  const insertManyResult = await collection.insertMany([
    { name: 'Jane', email: 'jane@example.com', age: 25 },
    { name: 'Bob', email: 'bob@example.com', age: 35 }
  ]);
  
  // 读取(Read)
  // 查找单个文档
  const user = await collection.findOne({ name: 'John' });
  console.log('用户:', user);
  
  // 查找多个文档
  const users = await collection.find({ age: { $gte: 30 } }).toArray();
  console.log('30岁以上的用户:', users);
  
  // 更新(Update)
  const updateResult = await collection.updateOne(
    { name: 'John' },
    { $set: { age: 31 } }
  );
  console.log('更新文档数:', updateResult.modifiedCount);
  
  // 更新多个文档
  const updateManyResult = await collection.updateMany(
    { age: { $lt: 30 } },
    { $set: { status: 'young' } }
  );
  
  // 删除(Delete)
  const deleteResult = await collection.deleteOne({ name: 'John' });
  console.log('删除文档数:', deleteResult.deletedCount);
  
  // 删除多个文档
  const deleteManyResult = await collection.deleteMany({ age: { $gt: 40 } });
}

查询操作

javascript
async function queryOperations() {
  const db = await connect();
  const collection = db.collection('users');
  
  // 条件查询
  const users = await collection.find({
    age: { $gte: 25, $lte: 35 },
    email: { $regex: /@example\.com$/ }
  }).toArray();
  
  // 排序
  const sortedUsers = await collection
    .find()
    .sort({ age: -1 }) // 降序
    .toArray();
  
  // 限制和跳过
  const paginatedUsers = await collection
    .find()
    .skip(10)  // 跳过前 10 条
    .limit(20) // 限制 20 条
    .toArray();
  
  // 投影(选择字段)
  const userNames = await collection
    .find({}, { projection: { name: 1, email: 1 } })
    .toArray();
  
  // 计数
  const count = await collection.countDocuments({ age: { $gte: 30 } });
  console.log('30岁以上的用户数:', count);
}

索引

javascript
async function createIndexes() {
  const db = await connect();
  const collection = db.collection('users');
  
  // 创建单字段索引
  await collection.createIndex({ email: 1 });
  
  // 创建唯一索引
  await collection.createIndex({ email: 1 }, { unique: true });
  
  // 创建复合索引
  await collection.createIndex({ name: 1, age: -1 });
  
  // 查看索引
  const indexes = await collection.indexes();
  console.log('索引列表:', indexes);
}

Mongoose ODM

Mongoose 是 MongoDB 的对象文档映射(ODM)库。

安装和连接

bash
npm install mongoose
javascript
const mongoose = require('mongoose');

const uri = 'mongodb://localhost:27017/mydb';

async function connect() {
  try {
    await mongoose.connect(uri);
    console.log('Mongoose 连接成功');
  } catch (err) {
    console.error('连接失败:', err);
  }
}

定义模型

javascript
const mongoose = require('mongoose');

// 定义 Schema
const userSchema = new mongoose.Schema({
  name: {
    type: String,
    required: true,
    trim: true
  },
  email: {
    type: String,
    required: true,
    unique: true,
    lowercase: true
  },
  age: {
    type: Number,
    min: 0,
    max: 120
  },
  createdAt: {
    type: Date,
    default: Date.now
  }
});

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

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

// 创建模型
const User = mongoose.model('User', userSchema);

module.exports = User;

使用模型

javascript
// 创建文档
const user = new User({
  name: 'John',
  email: 'john@example.com',
  age: 30
});

await user.save();

// 或者使用 create
const newUser = await User.create({
  name: 'Jane',
  email: 'jane@example.com',
  age: 25
});

// 查询
const users = await User.find({ age: { $gte: 30 } });
const user = await User.findById(userId);
const userByEmail = await User.findByEmail('john@example.com');

// 更新
await User.updateOne({ _id: userId }, { age: 31 });
await User.findByIdAndUpdate(userId, { age: 31 }, { new: true });

// 删除
await User.deleteOne({ _id: userId });
await User.findByIdAndDelete(userId);

MySQL 操作

安装和连接

bash
npm install mysql2
javascript
const mysql = require('mysql2/promise');

async function connect() {
  const connection = await mysql.createConnection({
    host: 'localhost',
    user: 'root',
    password: 'password',
    database: 'mydb'
  });
  
  console.log('连接 MySQL 成功');
  return connection;
}

基本操作

javascript
async function mysqlOperations() {
  const connection = await connect();
  
  try {
    // 查询
    const [rows] = await connection.execute(
      'SELECT * FROM users WHERE age >= ?',
      [30]
    );
    console.log('用户列表:', rows);
    
    // 插入
    const [result] = await connection.execute(
      'INSERT INTO users (name, email, age) VALUES (?, ?, ?)',
      ['John', 'john@example.com', 30]
    );
    console.log('插入 ID:', result.insertId);
    
    // 更新
    const [updateResult] = await connection.execute(
      'UPDATE users SET age = ? WHERE id = ?',
      [31, userId]
    );
    console.log('影响行数:', updateResult.affectedRows);
    
    // 删除
    const [deleteResult] = await connection.execute(
      'DELETE FROM users WHERE id = ?',
      [userId]
    );
    
  } finally {
    await connection.end();
  }
}

连接池

javascript
const mysql = require('mysql2/promise');

const pool = mysql.createPool({
  host: 'localhost',
  user: 'root',
  password: 'password',
  database: 'mydb',
  waitForConnections: true,
  connectionLimit: 10,
  queueLimit: 0
});

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

Sequelize ORM

Sequelize 是 Node.js 的 ORM 框架,支持多种数据库。

安装和连接

bash
npm install sequelize mysql2
javascript
const { Sequelize } = require('sequelize');

const sequelize = new Sequelize('mydb', 'root', 'password', {
  host: 'localhost',
  dialect: 'mysql'
});

async function connect() {
  try {
    await sequelize.authenticate();
    console.log('Sequelize 连接成功');
  } catch (err) {
    console.error('连接失败:', err);
  }
}

定义模型

javascript
const { DataTypes } = require('sequelize');

const User = sequelize.define('User', {
  id: {
    type: DataTypes.INTEGER,
    primaryKey: true,
    autoIncrement: true
  },
  name: {
    type: DataTypes.STRING,
    allowNull: false
  },
  email: {
    type: DataTypes.STRING,
    allowNull: false,
    unique: true
  },
  age: {
    type: DataTypes.INTEGER,
    validate: {
      min: 0,
      max: 120
    }
  }
}, {
  tableName: 'users',
  timestamps: true
});

使用模型

javascript
// 创建
const user = await User.create({
  name: 'John',
  email: 'john@example.com',
  age: 30
});

// 查询
const users = await User.findAll({ where: { age: { [Op.gte]: 30 } } });
const user = await User.findByPk(userId);

// 更新
await User.update({ age: 31 }, { where: { id: userId } });
await user.update({ age: 31 });

// 删除
await User.destroy({ where: { id: userId } });
await user.destroy();

Redis 操作

安装和连接

bash
npm install redis
javascript
const redis = require('redis');
const client = redis.createClient({
  url: 'redis://localhost:6379'
});

client.on('error', (err) => console.error('Redis 错误:', err));

await client.connect();
console.log('Redis 连接成功');

基本操作

javascript
// 字符串操作
await client.set('key', 'value');
const value = await client.get('key');

// 设置过期时间
await client.setEx('key', 3600, 'value'); // 1 小时后过期

// 哈希操作
await client.hSet('user:1', {
  name: 'John',
  email: 'john@example.com',
  age: '30'
});
const user = await client.hGetAll('user:1');

// 列表操作
await client.lPush('list', 'item1', 'item2');
const items = await client.lRange('list', 0, -1);

// 集合操作
await client.sAdd('set', 'member1', 'member2');
const members = await client.sMembers('set');

数据库最佳实践

1. 连接管理

javascript
// 使用连接池
const pool = mysql.createPool({
  connectionLimit: 10,
  // ... 其他配置
});

// 使用单例模式管理连接
class Database {
  constructor() {
    this.connection = null;
  }
  
  async connect() {
    if (!this.connection) {
      this.connection = await mysql.createConnection(config);
    }
    return this.connection;
  }
}

2. 错误处理

javascript
async function safeQuery(query, params) {
  try {
    const [rows] = await connection.execute(query, params);
    return { success: true, data: rows };
  } catch (err) {
    console.error('查询错误:', err);
    return { success: false, error: err.message };
  }
}

3. 事务处理

javascript
// MongoDB 事务
const session = client.startSession();
try {
  await session.withTransaction(async () => {
    await collection1.insertOne({ data: 1 }, { session });
    await collection2.insertOne({ data: 2 }, { session });
  });
} finally {
  await session.endSession();
}

// MySQL 事务
await connection.beginTransaction();
try {
  await connection.execute('INSERT INTO ...');
  await connection.execute('UPDATE ...');
  await connection.commit();
} catch (err) {
  await connection.rollback();
  throw err;
}

总结

Node.js 数据库操作要点:

  • MongoDB:使用原生驱动或 Mongoose ODM
  • MySQL:使用 mysql2 或 Sequelize ORM
  • Redis:用于缓存和会话存储
  • 连接管理:使用连接池提高性能
  • 错误处理:统一的错误处理机制
  • 事务处理:确保数据一致性