Node.js 连接 MongoDB 完全指南(2025 最新版)
核心结论:使用官方驱动 mongodb@^6.0(原生)或 mongoose@^8.0(ODM)是 唯一推荐方式。
一、驱动对比
| 驱动 | 类型 | 推荐场景 | 最新版本 |
|---|---|---|---|
mongodb | 原生驱动 | 高性能、灵活、微服务 | 6.9.0 |
mongoose | ODM(Schema + Model) | 快速开发、团队协作、复杂业务 | 8.7.0 |
二、安装(一键搞定)
# 原生驱动
npm install mongodb
# 或 Mongoose(推荐大多数项目)
npm install mongoose
三、原生驱动 mongodb 连接(推荐生产)
1. 基础连接
import { MongoClient } from 'mongodb';
const uri = 'mongodb://localhost:27017/mydb';
const client = new MongoClient(uri);
async function run() {
try {
await client.connect();
const db = client.db('mydb');
console.log('连接成功!');
const collection = db.collection('users');
await collection.insertOne({ name: 'Alice', age: 25 });
const user = await collection.findOne({ name: 'Alice' });
console.log('查询结果:', user);
} finally {
await client.close();
}
}
run().catch(console.dir);
2. 副本集 + 认证 + 连接池(生产配置)
const uri = 'mongodb://user:pass@host1:27017,host2:27017,host3:27017/mydb'
+ '?replicaSet=rs0'
+ '&authSource=admin'
+ '&readPreference=secondaryPreferred'
+ '&maxPoolSize=50'
+ '&minPoolSize=10'
+ '&connectTimeoutMS=10000'
+ '&socketTimeoutMS=30000';
const client = new MongoClient(uri, {
tls: true,
tlsAllowInvalidCertificates: false, // 生产关闭
});
await client.connect();
console.log('副本集连接成功');
3. 单例模式(全局复用)
// db.js
import { MongoClient } from 'mongodb';
let client;
let clientPromise;
if (!process.env.MONGODB_URI) {
throw new Error('请配置 MONGODB_URI 环境变量');
}
if (process.env.NODE_ENV === 'development') {
// 开发环境:全局缓存避免热重载创建多个连接
if (!global._mongoClientPromise) {
client = new MongoClient(process.env.MONGODB_URI);
global._mongoClientPromise = client.connect();
}
clientPromise = global._mongoClientPromise;
} else {
// 生产环境
client = new MongoClient(process.env.MONGODB_URI);
clientPromise = client.connect();
}
export default clientPromise;
// 使用
import clientPromise from './db.js';
const client = await clientPromise;
const db = client.db('mydb');
四、Mongoose 连接(推荐快速开发)
1. 安装与连接
npm install mongoose
// mongoose.js
import mongoose from 'mongoose';
const MONGODB_URI = process.env.MONGODB_URI || 'mongodb://localhost:27017/mydb';
if (!MONGODB_URI) {
throw new Error('请配置 MONGODB_URI');
}
let cached = global.mongoose;
if (!cached) {
cached = global.mongoose = { conn: null, promise: null };
}
async function dbConnect() {
if (cached.conn) {
return cached.conn;
}
if (!cached.promise) {
const opts = {
bufferCommands: false,
maxPoolSize: 10,
};
cached.promise = mongoose.connect(MONGODB_URI, opts).then((mongoose) => {
return mongoose;
});
}
try {
cached.conn = await cached.promise;
console.log('Mongoose 连接成功');
} catch (e) {
cached.promise = null;
throw e;
}
return cached.conn;
}
export default dbConnect;
2. 定义 Schema 与 Model
// models/User.js
import mongoose from 'mongoose';
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
},
tags: [String],
createdAt: {
type: Date,
default: Date.now
}
}, {
timestamps: true // 自动添加 createdAt/updatedAt
});
export default mongoose.models.User || mongoose.model('User', userSchema);
3. 使用
import dbConnect from './mongoose.js';
import User from './models/User.js';
await dbConnect();
const user = await User.create({
name: 'Bob',
email: 'bob@example.com',
age: 30,
tags: ['dev', 'node']
});
const found = await User.findOne({ email: 'bob@example.com' });
console.log(found);
五、环境变量配置(.env)
# .env
MONGODB_URI=mongodb://user:pass@localhost:27017/mydb?replicaSet=rs0&authSource=admin
# Atlas 示例
# MONGODB_URI=mongodb+srv://user:pass@cluster0.xxxxx.mongodb.net/mydb
// 加载环境变量
import 'dotenv/config';
六、事务(ACID)
const session = await client.startSession();
try {
session.startTransaction();
await collection1.insertOne(doc1, { session });
await collection2.updateOne(filter, update, { session });
await session.commitTransaction();
} catch (error) {
await session.abortTransaction();
throw error;
} finally {
session.endSession();
}
要求:MongoDB ≥ 4.0 + 副本集/分片
七、连接池与性能优化
| 配置 | 推荐值 | 说明 |
|---|---|---|
maxPoolSize | 10-50 | 每 CPU 核 5-10 |
minPoolSize | 5 | 保持热连接 |
connectTimeoutMS | 10000 | 连接超时 |
socketTimeoutMS | 0 | 生产设 0(永不超时) |
serverSelectionTimeoutMS | 5000 | 选主超时 |
八、Docker 一键部署
# docker-compose.yml
version: '3.8'
services:
mongo:
image: mongo:7
ports:
- "27017:27017"
volumes:
- mongo-data:/data/db
command: --replSet rs0 --bind_ip_all
mongo-express:
image: mongo-express
ports:
- "8081:8081"
environment:
ME_CONFIG_MONGODB_URL: mongodb://mongo:27017
volumes:
mongo-data:
# 初始化副本集
docker exec -it <container> mongosh --eval 'rs.initiate()'
九、常见错误与解决方案
| 错误 | 原因 | 解决方案 |
|---|---|---|
MongoServerSelectionError | 连接字符串错误 | 检查 URI、防火墙 |
Authentication failed | 密码含特殊字符 | URL 编码或用 mongodb+srv |
Topology is closed | 连接未关闭 | 使用 try/finally |
Duplicate key | 唯一索引冲突 | 检查 _id 或 email |
Connection pool closed | 进程退出前未关闭 | 使用 process.on('SIGINT') |
十、完整项目结构
project/
├── config/
│ └── db.js
├── models/
│ └── User.js
├── .env
├── server.js
└── package.json
十一、学习资源
- 官方驱动:mongodb.js.org
- Mongoose 文档:mongoosejs.com
- Atlas 免费集群:mongodb.com/cloud/atlas
你现在可以:
npm install mongodb # 原生
npm install mongoose # ODM
告诉我你的需求,我给你代码:
- 使用
mongodb还是mongoose? - 项目类型:API / Next.js / Express?
- 是否需要 事务 / 分页 / 聚合?
回复 3 个关键词,我立刻生成完整可运行项目!