Node.js Driver
MongoDB Node driver: connection options, CRUD, aggregation, transactions, and the production patterns.
MongoDB — Node driver
EXAMPLE
// Install: npm install mongodb
import { MongoClient, ObjectId } from 'mongodb';
// ===== Connect =====
const client = new MongoClient(process.env.MONGO_URI, {
maxPoolSize: 50,
minPoolSize: 5,
serverSelectionTimeoutMS: 5000,
retryWrites: true,
retryReads: true,
appName: 'shop',
});
await client.connect();
const db = client.db('shop');
const users = db.collection('users');
// ===== Insert =====
const result = await users.insertOne({ email: 'a@x.io', name: 'Alex' });
console.log(result.insertedId);
await users.insertMany([{ email: 'b@x.io' }, { email: 'c@x.io' }]);
// ===== Find =====
const u = await users.findOne({ _id: new ObjectId(id) });
const cursor = users.find({ active: true })
.sort({ created_at: -1 })
.skip(0)
.limit(20)
.project({ password: 0 });
const list = await cursor.toArray();
// Cursor iteration (large results):
for await (const doc of users.find({ active: true })) {
// process one doc at a time
}
// ===== Update =====
await users.updateOne(
{ _id: new ObjectId(id) },
{ $set: { name: 'Sam' }, $inc: { logins: 1 } },
{ upsert: true }
);
const result2 = await users.updateMany(
{ country: 'AU' },
{ $set: { region: 'APAC' } }
);
console.log(result2.modifiedCount);
// ===== Delete =====
await users.deleteOne({ _id: new ObjectId(id) });
await users.deleteMany({ created_at: { $lt: cutoff } });
// ===== Aggregation =====
const stats = await db.collection('orders').aggregate([
{ $match: { status: 'paid' } },
{ $group: { _id: '$customer_id', total: { $sum: '$amount' } } },
{ $sort: { total: -1 } },
{ $limit: 10 },
]).toArray();
// ===== Indexes =====
await users.createIndex({ email: 1 }, { unique: true });
await users.createIndexes([
{ key: { country: 1, region: 1 } },
{ key: { created_at: -1 } },
]);
const indexes = await users.indexes();
// ===== Transactions =====
const session = client.startSession();
try {
await session.withTransaction(async () => {
await accounts.updateOne({ _id: from }, { $inc: { balance: -50 } }, { session });
await accounts.updateOne({ _id: to }, { $inc: { balance: 50 } }, { session });
});
} finally {
await session.endSession();
}
// ===== Bulk operations =====
const bulk = users.initializeUnorderedBulkOp();
for (const u of inserts) bulk.insert(u);
for (const u of updates) bulk.find({ _id: u._id }).update({ $set: u });
await bulk.execute();
// ===== Lifecycle =====
process.on('SIGTERM', async () => {
await client.close();
process.exit(0);
});
// ===== Patterns =====
// - One client per process; reuse across requests
// - Use cursors for large result sets; do not toArray() millions of docs
// - Set appName for ops + slow query attribution
// - Bulk ops for write-heavy workflows
// - Replica set + transactions only when needed
// ===== Pitfalls =====
// - Connecting per request (slow + connection leak)
// - Missing indexes -> COLLSCAN
// - Forgetting projection -> shipping every field including secrets
// - Transactions on standalone server -> error (replica set required)
Why it matters
The official Node driver is fast + minimal. Connect once, reuse, project explicitly, paginate via cursor, index for queries, bulk for writes, transactions only when needed. Add appName + retry settings for production observability.
Tip: Tweak the snippet with Try it Yourself », then sit the quiz at the bottom of the page.
Example
Example
import { MongoClient } from 'mongodb';
const client = new MongoClient(uri);
await client.connect();
const db = client.db('shop');
Try it Yourself »
Discussion
Loading…