Node.js 连接 MongoDB

Node.js 连接 MongoDB 完全指南(2025 最新版)

核心结论:使用官方驱动 mongodb@^6.0(原生)或 mongoose@^8.0(ODM)是 唯一推荐方式


一、驱动对比

驱动类型推荐场景最新版本
mongodb原生驱动高性能、灵活、微服务6.9.0
mongooseODM(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 + 副本集/分片


七、连接池与性能优化

配置推荐值说明
maxPoolSize10-50每 CPU 核 5-10
minPoolSize5保持热连接
connectTimeoutMS10000连接超时
socketTimeoutMS0生产设 0(永不超时)
serverSelectionTimeoutMS5000选主超时

八、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唯一索引冲突检查 _idemail
Connection pool closed进程退出前未关闭使用 process.on('SIGINT')

十、完整项目结构

project/
├── config/
│   └── db.js
├── models/
│   └── User.js
├── .env
├── server.js
└── package.json

十一、学习资源


你现在可以:

npm install mongodb        # 原生
npm install mongoose       # ODM

告诉我你的需求,我给你代码:

  1. 使用 mongodb 还是 mongoose
  2. 项目类型:API / Next.js / Express
  3. 是否需要 事务 / 分页 / 聚合

回复 3 个关键词,我立刻生成完整可运行项目!

文章已创建 2371

发表回复

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

相关文章

开始在上面输入您的搜索词,然后按回车进行搜索。按ESC取消。

返回顶部