Cơ sở dữ liệu và Node.js
Dưới đây là phần giải thích đầy đủ và chuyên sâu theo góc nhìn của Senior Backend Developer về cách Node.js tương tác với cơ sở dữ liệu, sử dụng Mongoose, và quản lý kết nối hiệu quả:
✅ 1. Node.js tương tác với cơ sở dữ liệu như thế nào?
Node.js có thể kết nối với hầu hết các loại cơ sở dữ liệu thông qua drivers hoặc ORM/ODM, phổ biến nhất là:
🔹 Quan hệ (SQL): MySQL, PostgreSQL, MSSQL
Dùng các driver như:
mysql2
,pg
,sequelize
,typeorm
.
🔹 Phi quan hệ (NoSQL): MongoDB, Redis
MongoDB: dùng
mongoose
,mongodb
.Redis: dùng
ioredis
,node-redis
.
✅ Ví dụ: MySQL
const mysql = require('mysql2');
const pool = mysql.createPool({
host: 'localhost',
user: 'root',
database: 'test'
});
pool.query('SELECT * FROM users', (err, results) => {
if (err) throw err;
console.log(results);
});
✅ Ví dụ: MongoDB (native)
const { MongoClient } = require('mongodb');
const client = new MongoClient('mongodb://localhost:27017');
await client.connect();
const db = client.db('test');
const users = await db.collection('users').find().toArray();
✅ 2. Mongoose là gì và cách sử dụng với MongoDB trong Node.js
🔹 Mongoose là gì?
Mongoose là một ODM (Object Data Modeling) cho MongoDB, giúp:
Định nghĩa schema rõ ràng.
Mapping giữa documents và JS objects.
Có tính năng middleware, validation, và query helpers.
✅ Cách sử dụng Mongoose cơ bản:
1. Cài đặt
npm install mongoose
2. Kết nối MongoDB
const mongoose = require('mongoose');
mongoose.connect('mongodb://localhost:27017/test', {
useNewUrlParser: true,
useUnifiedTopology: true
});
3. Định nghĩa Schema và Model
const userSchema = new mongoose.Schema({
name: String,
email: String,
createdAt: { type: Date, default: Date.now }
});
const User = mongoose.model('User', userSchema);
4. CRUD Example
// Create
const user = await User.create({ name: 'Tài', email: 'tai@example.com' });
// Read
const users = await User.find();
// Update
await User.updateOne({ _id: user._id }, { name: 'Tài Titans' });
// Delete
await User.deleteOne({ _id: user._id });
✅ 3. Quản lý kết nối cơ sở dữ liệu trong Node.js để tránh rò rỉ bộ nhớ
🔹 Vấn đề thường gặp:
Kết nối bị mở nhưng không đóng.
Quá nhiều kết nối gây "connection pool exhaustion".
Reconnect logic sai khi server restart hoặc DB bị down.
✅ Best Practices:
🔸 1. Dùng Connection Pool
Dùng pool để tái sử dụng kết nối:
MySQL:
mysql2.createPool()
MongoDB: Mongoose tự động quản lý pool.
🔸 2. Xử lý kết nối toàn cục (Singleton)
// db.js
const mongoose = require('mongoose');
let conn = null;
async function connectDB() {
if (conn) return conn;
conn = await mongoose.connect(process.env.MONGO_URI, {
useNewUrlParser: true,
useUnifiedTopology: true,
});
return conn;
}
module.exports = connectDB;
🔸 3. Đóng kết nối đúng cách
process.on('SIGINT', async () => {
await mongoose.disconnect();
process.exit(0);
});
🔸 4. Xử lý lỗi khi mất kết nối
mongoose.connection.on('error', err => {
console.error('MongoDB Error:', err);
});
mongoose.connection.on('disconnected', () => {
console.warn('MongoDB disconnected. Attempting to reconnect...');
});
✅ Tổng kết:
Mục
Nội dung chính
Tương tác DB
Dùng driver (MySQL, MongoDB) hoặc ORM/ODM
Mongoose
ODM giúp define schema, validation, và thao tác Mongo dễ dàng
Quản lý kết nối
Dùng pool, singleton pattern, handle errors và close đúng cách
Tránh rò rỉ bộ nhớ
Không tạo quá nhiều kết nối, đóng kết nối khi không dùng
Last updated