Node.js 连接 MongoDB(一文讲透)

更新时间:

💡一则或许对你有用的小广告

欢迎加入小哈的星球 ,你将获得:专属的项目实战 / 1v1 提问 / Java 学习路线 / 学习打卡 / 每月赠书 / 社群讨论

  • 新项目:《从零手撸:仿小红书(微服务架构)》 正在持续爆肝中,基于 Spring Cloud Alibaba + Spring Boot 3.x + JDK 17...点击查看项目介绍 ;
  • 《从零手撸:前后端分离博客项目(全栈开发)》 2 期已完结,演示链接: http://116.62.199.48/ ;

截止目前, 星球 内专栏累计输出 82w+ 字,讲解图 3441+ 张,还在持续爆肝中.. 后续还会上新更多项目,目标是将 Java 领域典型的项目都整一波,如秒杀系统, 在线商城, IM 即时通讯,权限管理,Spring Cloud Alibaba 微服务等等,已有 2900+ 小伙伴加入学习 ,欢迎点击围观

前言:为什么需要 Node.js 连接 MongoDB?

在现代 Web 开发中,Node.js 与 MongoDB 的组合因其高性能、灵活性和易用性,成为构建实时应用、API 后端和数据密集型项目的核心选择。Node.js 的非阻塞 I/O 特性与 MongoDB 的文档数据库模型高度契合,两者结合可以显著提升开发效率。

想象一下,Node.js 就像一位高效的快递员,负责快速处理请求和响应;而 MongoDB 则像一个智能仓储系统,能够灵活存储和检索数据。Node.js 连接 MongoDB 的过程,就像是快递员与仓储系统建立通信,从而实现数据的高效传递与管理。

本文将从零开始,逐步讲解如何在 Node.js 中连接 MongoDB,覆盖环境搭建、基础操作、错误处理和性能优化等核心知识点,并通过实际案例帮助读者快速上手。


一、环境准备:搭建开发基础

1.1 安装 Node.js 和 MongoDB

在开始之前,确保本地环境已安装以下工具:

  • Node.js(建议版本 18+):访问 Node.js 官网 下载并安装。
  • MongoDB(建议版本 6+):通过 MongoDB 官网 下载社区版,或使用 Docker 快速启动容器。

1.2 安装 MongoDB 驱动或 ORM

Node.js 与 MongoDB 的交互可通过两种方式实现:

  1. 原生驱动(mongodb 包):直接调用 MongoDB 的官方 Node.js 驱动,适合需要精细控制的场景。
  2. Mongoose ORM:一个基于原生驱动的封装库,提供更简洁的 API 和数据验证功能,适合复杂项目。

安装依赖

通过 npm 安装所需的包:

npm install mongodb  

npm install mongoose

二、连接 MongoDB 的核心步骤

2.1 使用原生驱动连接

原生驱动提供了直接操作数据库的接口。以下是连接的基本流程:

步骤 1:导入模块并创建客户端

const { MongoClient } = require("mongodb");

// 连接字符串示例(替换为你的数据库地址)
const uri = "mongodb://localhost:27017";  

// 创建客户端实例
const client = new MongoClient(uri);

步骤 2:连接数据库并执行操作

async function run() {
  try {
    await client.connect(); // 建立连接
    const database = client.db("myDatabase"); // 选择数据库
    const collection = database.collection("users"); // 选择集合(表)

    // 示例:插入一条数据
    const result = await collection.insertOne({ name: "Alice", age: 30 });
    console.log("Inserted 1 document:", result.insertedId);
  } finally {
    await client.close(); // 关闭连接
  }
}

run().catch(console.dir);

连接字符串的含义

MongoDB 的 URI 格式如下:

mongodb://[username:password@]host:port/database?option1=value1&option2=value2  

例如:

mongodb://admin:password@localhost:27017/myDatabase?retryWrites=true&w=majority  
  • host:port:MongoDB 服务器地址和端口(默认 27017)。
  • username:password:可选,用于认证。
  • options:如 retryWrites 控制写入重试行为。

2.2 使用 Mongoose 简化连接

Mongoose 通过模式(Schema)和模型(Model)抽象简化了操作流程。

步骤 1:定义数据模型

const mongoose = require("mongoose");

// 定义用户模式
const userSchema = new mongoose.Schema({
  name: String,
  age: Number,
  email: {
    type: String,
    required: true, // 必填字段
    unique: true    // 唯一性约束
  }
});

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

步骤 2:连接数据库并执行操作

async function main() {
  await mongoose.connect("mongodb://localhost:27017/myDatabase");
  console.log("Connected to MongoDB!");

  // 插入数据
  const user = new User({ name: "Bob", age: 25, email: "bob@example.com" });
  await user.save();

  // 查询数据
  const users = await User.find({ age: { $gt: 20 } });
  console.log(users);
}

main().catch(err => console.error(err));

Mongoose 的优势

  • 数据验证:通过 Schema 定义字段规则(如 requiredunique)。
  • 静态方法/实例方法:可为模型添加自定义方法。
  • 中间件:如 pre('save') 在保存前自动执行操作(如哈希密码)。

三、CRUD 操作详解

3.1 创建(Create)

原生驱动示例

const result = await collection.insertOne({ name: "Charlie", score: 95 });
console.log(`Inserted document ID: ${result.insertedId}`);

Mongoose 示例

const user = new User({ name: "David", email: "david@example.com" });
await user.save(); // 自动保存到数据库

3.2 读取(Read)

查询条件与操作符

MongoDB 支持丰富的查询条件,例如:

  • { age: { $gt: 30 } }:年龄大于 30
  • { $or: [ { name: "Eve" }, { score: { $lt: 60 } } ] }:或条件

分页与排序

// 原生驱动分页查询
const cursor = collection.find({}).limit(10).skip(20).sort({ age: -1 });
const results = await cursor.toArray();

3.3 更新(Update)

修改单条文档

// 更新 name 为 Alice 的用户,设置 age 为 35
const updateResult = await collection.updateOne(
  { name: "Alice" },
  { $set: { age: 35 } }
);

Mongoose 的更新方法

await User.updateOne({ name: "Bob" }, { $inc: { age: 1 } }); // 年龄+1

3.4 删除(Delete)

// 删除所有 age 小于 20 的文档
const deleteResult = await collection.deleteMany({ age: { $lt: 20 } });

四、错误处理与最佳实践

4.1 异常捕获

在异步操作中,务必使用 try...catch.catch() 捕获错误:

try {
  await client.connect();
} catch (error) {
  console.error("连接失败:", error);
}

常见错误类型

  • ECONNREFUSED:数据库地址错误或服务未启动。
  • MongoServerError:操作违反约束(如唯一索引冲突)。

4.2 连接池优化

原生驱动和 Mongoose 默认使用连接池。可通过配置优化性能:

// 原生驱动设置最大连接数
const client = new MongoClient(uri, { maxPoolSize: 50 });

4.3 索引与性能

为高频查询字段添加索引:

await collection.createIndex({ email: 1 }, { unique: true });

五、实战案例:构建用户管理系统

5.1 项目结构

my-app/  
├── models/  
│   └── user.js  # 用户模型定义  
├── controllers/  
│   └── userController.js  # 业务逻辑  
├── routes/  
│   └── userRoutes.js  # 路由配置  
└── server.js         # 主入口文件  

5.2 实现用户注册功能

定义用户模型(user.js)

const mongoose = require("mongoose");

const userSchema = new mongoose.Schema({
  username: { type: String, required: true, unique: true },
  email: { type: String, required: true, unique: true },
  password: { type: String, required: true },
  createdAt: { type: Date, default: Date.now }
});

module.exports = mongoose.model("User", userSchema);

路由与控制器(userRoutes.js)

const express = require("express");
const router = express.Router();
const UserController = require("../controllers/userController");

router.post("/register", UserController.registerUser);

module.exports = router;

处理注册逻辑(userController.js)

exports.registerUser = async (req, res) => {
  try {
    const { username, email, password } = req.body;
    const existingUser = await User.findOne({ email });

    if (existingUser) {
      return res.status(409).json({ error: "邮箱已注册" });
    }

    const user = new User({ username, email, password });
    await user.save();
    res.status(201).json({ message: "注册成功" });
  } catch (error) {
    res.status(500).json({ error: error.message });
  }
};

六、进阶技巧与常见问题

6.1 环境变量管理

敏感信息(如数据库 URI)应通过环境变量存储:

// .env 文件
MONGODB_URI=mongodb://localhost:27017/myDatabase  

// server.js
require("dotenv").config();
const uri = process.env.MONGODB_URI;

6.2 多数据库连接

在复杂项目中,可通过多个客户端实例连接不同数据库:

const client1 = new MongoClient(uri1);
const client2 = new MongoClient(uri2);

6.3 异步操作并发控制

使用 Promise.all() 并行执行多个查询:

const [users, posts] = await Promise.all([
  User.find({ role: "admin" }),
  Post.find({ published: true })
]);

结论:掌握 Node.js 连接 MongoDB 的关键

通过本文,我们从环境搭建、基础操作到实战案例,系统学习了如何用 Node.js 连接 MongoDB。核心要点包括:

  • 驱动选择:根据项目需求选择原生驱动或 Mongoose。
  • 错误处理:通过 try/catch 和中间件增强健壮性。
  • 性能优化:合理使用索引、连接池和分页策略。

掌握这些技能后,你可以进一步探索更高级的主题,如聚合管道(Aggregation Pipeline)、实时数据更新(Change Streams),或结合其他技术(如 Express、React)构建完整应用。记住,Node.js 连接 MongoDB 是一个起点,而持续实践和探索将帮助你成为全栈开发的专家。

现在,不妨动手创建一个小型项目,例如待办事项列表或博客系统,将所学知识付诸实践!

最新发布