使用官方 Node.js 驱动程序连接
您将创建 MongoClient,管理连接池,并在 Node.js 应用中使用原生驱动程序执行 CRUD 操作。
使用官方 Node.js 驱动程序连接 是 CoddyKit 上的免费 MongoDB Academy 课时。 这是第 1 节课,共 4 节。 你可以在下方免费阅读本课时的完整内容 — 然后在浏览器中使用内置代码编辑器和全天候 AI 导师进行实践。 这是 MongoDB Academy 学习路径的一部分,你的进度在网页和 CoddyKit 应用中同步。 MongoDB Academy 课程共包含 4 节课。
官方 MongoDB Node.js 驱动程序
MongoDB Node.js 驱动程序(mongodb npm 软件包)是用于从 Node.js 应用程序连接 MongoDB 的官方底层库。它无需抽象层即可直接访问 MongoDB 的所有功能,因此非常适合对性能要求较高的代码、微服务和脚本。该驱动程序由 MongoDB 公司维护,并且会紧密跟进 MongoDB 服务器的新功能。
// Install the driver
// npm install mongodb
// Or with yarn:
// yarn add mongodb
// The driver exports MongoClient as its main entry point
const { MongoClient, ObjectId, ServerApiVersion } = require('mongodb');
// or ES module:
// import { MongoClient, ObjectId } from 'mongodb';创建 MongoClient
MongoClient 类是所有交互的入口点。请使用您的连接字符串(URI)以及可选的选项对象对其实例化。连接字符串会编码主机、端口、凭据和连接参数。对于 MongoDB Atlas,请从 Atlas 界面复制连接字符串,并替换密码占位符。每个应用程序只创建一个 MongoClient 并重复使用,不要为每个请求创建新的 MongoClient。
const { MongoClient, ServerApiVersion } = require('mongodb');
const uri = process.env.MONGODB_URI;
// URI format: mongodb+srv://<user>:<password>@cluster0.xxxxx.mongodb.net/?retryWrites=true
const client = new MongoClient(uri, {
serverApi: {
version: ServerApiVersion.v1,
strict: true,
deprecationErrors: true
}
});
// client is not yet connected — connecting happens lazily or via connect()连接到 MongoDB
调用 client.connect() 来建立连接池。该驱动程序会维护一个连接池,通常包含 5 到 100 个与服务器的连接,并在各项操作之间重复使用这些连接。您只需在应用程序启动时调用一次 connect()。您也可以直接调用操作而不显式调用 connect()——驱动程序会在第一次操作时延迟建立连接。请在应用程序关闭时调用 client.close()。
async function main() {
try {
await client.connect();
console.log('Connected to MongoDB');
// Get database reference
const db = client.db('myDatabase');
// Ping the server to verify connection
await db.command({ ping: 1 });
console.log('Ping successful');
// Run your application logic here...
} finally {
// Always close when done
await client.close();
}
}
main().catch(console.error);Web 服务器的单例模式
在 Web 服务器(Express、Fastify、NestJS)中,MongoClient 必须是一个模块级单例,在启动时创建一次,并由所有请求处理程序共享。为每个请求创建新的 MongoClient 会耗尽可用连接,并严重降低性能。标准模式是在服务器启动函数中建立连接,然后导出客户端或数据库引用。
// db.js — module-level singleton
const { MongoClient } = require('mongodb');
let client;
let db;
async function connectToDatabase() {
if (db) return db; // return existing connection
client = new MongoClient(process.env.MONGODB_URI);
await client.connect();
db = client.db(process.env.DB_NAME || 'myapp');
return db;
}
module.exports = { connectToDatabase };
// In your Express app:
// const { connectToDatabase } = require('./db');
// const db = await connectToDatabase();
// app.locals.db = db;获取集合引用
通过调用 db.collection('collectionName') 访问集合。此调用不会发起网络请求,而是返回一个Collection 对象,也就是一个引用。您可以在启动时获取集合引用并将其存储为模块级变量,也可以在每个函数中内联获取。集合引用非常轻量,可以安全地在各个请求之间重复使用。
const db = client.db('ecommerce');
// Get collection references
const usersCollection = db.collection('users');
const ordersCollection = db.collection('orders');
const productsCollection = db.collection('products');
// TypeScript: provide a document type for type safety
// const users = db.collection<UserDocument>('users');
// Collections can also be retrieved inline:
async function getUser(id) {
return client.db('ecommerce').collection('users').findOne({ _id: id });
}增删改查操作:插入
使用 insertOne() 或 insertMany() 插入文档。如果未提供 _id,驱动程序会自动生成,并返回插入的 ID。结果对象中的 insertedId(用于 insertOne)或 insertedIds 映射(用于 insertMany)可以帮助您追踪创建的内容。这两种操作都接受一个 options 对象,您可以在其中指定 writeConcern。
const db = client.db('shop');
const products = db.collection('products');
// Insert one document
const insertResult = await products.insertOne({
name: 'Mechanical Keyboard',
price: 149.99,
category: 'Electronics',
stock: 50
});
console.log('Inserted ID:', insertResult.insertedId);
// Insert multiple documents
const bulkResult = await products.insertMany([
{ name: 'Mouse Pad', price: 19.99, category: 'Accessories' },
{ name: 'USB Hub', price: 39.99, category: 'Electronics' }
]);
console.log('Inserted count:', bulkResult.insertedCount);增删改查操作:读取
使用 findOne(filter) 获取单个文档,或使用 find(filter) 获取一个遍历所有匹配文档的游标。对于较小的结果集,可以使用 .toArray() 将游标转换为数组;对于较大的结果集,可以使用 for await...of 进行迭代。这两种方法都接受第二个选项参数,可用于指定 projection、sort、skip、limit 和其他查询修饰符。
const users = db.collection('users');
// Find a single user by email
const user = await users.findOne(
{ email: 'alice@example.com' },
{ projection: { password: 0 } } // exclude sensitive fields
);
// Find multiple documents with options
const activeUsers = await users.find(
{ active: true, role: 'admin' },
{
projection: { name: 1, email: 1 },
sort: { createdAt: -1 },
limit: 50
}
).toArray();
// Iterate large results without loading all into memory
const cursor = users.find({ active: true });
for await (const user of cursor) {
await processUser(user);
}增删改查操作:更新
使用 updateOne()、updateMany() 或 findOneAndUpdate() 更新文档。筛选条件决定要更新哪些文档,更新文档则使用 $set、$inc 和 $push 等运算符指定更改内容。updateOne() 和 updateMany() 会返回包含 matchedCount 和 modifiedCount 的结果。使用 upsert: true 可以在文档不存在时创建它。
const orders = db.collection('orders');
// Update one order's status
const updateResult = await orders.updateOne(
{ _id: orderId },
{ $set: { status: 'shipped', shippedAt: new Date() } }
);
console.log('Modified:', updateResult.modifiedCount);
// Atomic: find, update, and return the updated document
const updatedOrder = await orders.findOneAndUpdate(
{ _id: orderId },
{ $set: { status: 'delivered' }, $push: { statusHistory: { status: 'delivered', at: new Date() } } },
{ returnDocument: 'after' } // return the document AFTER update
);增删改查操作:删除
使用 deleteOne() 或 deleteMany() 删除文档。筛选条件决定要删除哪些文档。结果中包含 deletedCount。为确保生产环境安全,在运行 deleteMany 之前,请始终先使用 find 测试筛选条件——意外删除集合中的所有文档是一种常见且灾难性的错误。对于审计追踪,可以考虑使用软删除(设置 deletedAt 字段),而不是执行物理删除。
const sessions = db.collection('sessions');
// Delete one session
const deleteResult = await sessions.deleteOne({ _id: sessionId });
console.log('Deleted:', deleteResult.deletedCount);
// Delete all expired sessions — test filter first!
const thirtyDaysAgo = new Date(Date.now() - 30 * 24 * 60 * 60 * 1000);
// 1. Test: how many would be deleted?
const count = await sessions.countDocuments({ expiresAt: { $lt: thirtyDaysAgo } });
console.log('Would delete:', count);
// 2. Only delete after confirming the count looks right
if (count < 10000) { // sanity check
await sessions.deleteMany({ expiresAt: { $lt: thirtyDaysAgo } });
}运行聚合管道
使用 collection.aggregate(pipeline) 执行聚合管道。该调用会返回一个游标,您可以将其转换为数组或进行迭代。管道阶段以对象数组的形式传入。驱动程序会将管道发送到 MongoDB 的聚合引擎,并以流式方式返回结果。对于非常大的结果集,请直接迭代游标,而不要调用 .toArray(),以避免一次性将所有内容加载到内存中。
const orders = db.collection('orders');
// Revenue report by category
const report = await orders.aggregate([
{ $match: { status: 'completed', createdAt: { $gte: new Date('2024-01-01') } } },
{ $group: { _id: '$category', total: { $sum: '$amount' }, count: { $sum: 1 } } },
{ $sort: { total: -1 } }
]).toArray();
console.log('Revenue report:', report);
// For large aggregations, iterate the cursor:
const cursor = orders.aggregate([...largeComplexPipeline]);
for await (const doc of cursor) {
await writeToReport(doc);
}连接池配置
MongoClient 会维护一个连接池,自动管理与服务器的连接。关键选项包括:maxPoolSize(最大连接数,每个主机默认为 5)、minPoolSize(保持活动状态的最小连接数)、connectTimeoutMS 和 socketTimeoutMS。对于高流量 API,请增大 maxPoolSize,但要权衡 MongoDB 每个连接的内存开销。请使用 Atlas 指标监控连接池的使用情况。
const client = new MongoClient(uri, {
maxPoolSize: 20, // max 20 connections to the server
minPoolSize: 5, // keep at least 5 connections warm
connectTimeoutMS: 5000, // fail fast if can't connect in 5s
socketTimeoutMS: 45000, // idle socket timeout
serverSelectionTimeoutMS: 5000 // how long to wait to find an available server
});快速检查
请测试您对本课 MongoDB 和 NoSQL 数据库概念的理解。
课程回顾
本课您学到了:在启动时创建一个 MongoClient,并以单例形式重复使用——绝不要为每个请求创建一个;使用 client.db() 和 db.collection() 获取数据库和集合引用——这些都是轻量级的对象引用;以及使用 insertOne/insertMany、findOne/find、updateOne/updateMany/findOneAndUpdate 和 deleteOne/deleteMany 执行增删改查操作。接下来,我们将探索 Mongoose 的 Schema、Model 和虚拟字段,了解这种基于原生驱动程序的更高层抽象。
用 AI 导师学习 JavaScript — 免费
在浏览器中编写并运行真实代码,获得全天候 AI 导师的即时帮助,并在网页或应用中继续学习。
- 课程
- 30
- 课程
- 120
常见问题解答
「使用官方 Node.js 驱动程序连接」课时是免费的吗?
是的 — 「使用官方 Node.js 驱动程序连接」的完整文本可在网页上免费阅读。要进行交互式练习(内置代码编辑器和全天候 AI 导师)并解锁 MongoDB Academy 课程的其余内容,请升级到 CoddyKit PRO。 MongoDB Academy 课程共包含 4 节课。
「使用官方 Node.js 驱动程序连接」这节课中我会学到什么?
您将创建 MongoClient,管理连接池,并在 Node.js 应用中使用原生驱动程序执行 CRUD 操作。 你通过在浏览器中直接运行的动手代码来练习 MongoDB Academy,全天候 AI 导师会在你学习这节课的过程中回答你的问题。
学习 MongoDB Academy 需要有经验吗?
无需任何先前经验。CoddyKit 上的 MongoDB Academy 课程适合初学者到高级学习者,你可以从这里开始或从头开始,按照自己的节奏学习。 这是第 1 节课,共 4 节。
「使用官方 Node.js 驱动程序连接」课时需要多长时间?
大多数 CoddyKit 课程大约需要 5–10 分钟。每节课都很精短且互动,所以你能稳步进步,并在网页和应用中从离开的地方继续。
我能在这节 MongoDB Academy 课中编写并运行代码吗?
能。每节 MongoDB Academy 课都包含内置代码编辑器,你可以在浏览器中直接编写并运行真实代码,并获得即时 AI 反馈 — 无需本地设置。
此课程中的所有课时
- 使用官方 Node.js 驱动程序连接
- Mongoose 模式、模型和虚拟属性
- Mongoose 查询、链式调用和精简文档
- Mongoose 中间件:前置和后置钩子