Membaca Dokumen dengan Driver Node.js
Hubungkan skrip Node.js ke MongoDB dan lakukan operasi insert/find menggunakan driver resmi.
Membaca Dokumen dengan Driver Node.js adalah pelajaran MongoDB Academy gratis di CoddyKit. Ini adalah pelajaran 4 dari 4. Kamu bisa membaca pelajaran lengkapnya di bawah secara gratis — lalu praktikkan langsung di browser dengan editor kode bawaan dan tutor AI 24/7. Ini adalah bagian dari jalur belajar MongoDB Academy, dan progresmu tersinkronisasi di web dan aplikasi CoddyKit. Kursus MongoDB Academy mencakup 4 pelajaran total.
Bagian dari pelajaran ini belum diterjemahkan dan ditampilkan dalam bahasa Inggris.
The Official Node.js Driver
The MongoDB Node.js driver (mongodb npm package) is the official, low-level client for connecting to MongoDB from Node.js. It is maintained by MongoDB Inc., supports the full MongoDB API, and ships with TypeScript type definitions.
The driver exposes a MongoClient class that manages a connection pool—a set of pre-established TCP connections reused across requests. This eliminates the overhead of creating a new connection for every operation. Most production Node.js apps share a single MongoClient instance for the lifetime of the process.
# Install the MongoDB Node.js driver
npm install mongodb
# TypeScript types are included - no @types/mongodb neededCreating a MongoClient and Connecting
Create a MongoClient with your connection string URI and call connect(). The connection is not established until connect() (or the first operation). Once connected, retrieve a database reference with client.db('dbName') and a collection reference with db.collection('collName').
Best practice: create the MongoClient once at application startup and export/inject it. Do NOT create a new client per request—this exhausts file descriptors and defeats the connection pool.
const { MongoClient } = require('mongodb');
const uri = process.env.MONGODB_URI || 'mongodb://localhost:27017';
const client = new MongoClient(uri);
async function main() {
await client.connect();
console.log('Connected to MongoDB');
const db = client.db('myapp');
const users = db.collection('users');
// ... perform operations ...
await client.close();
}
main().catch(console.error);Connection Pool and Options
The MongoClient maintains a connection pool of open TCP connections. When an operation needs to run, it borrows a connection from the pool, executes the operation, and returns the connection. Key pool options:
maxPoolSize(default 100): maximum simultaneous connectionsminPoolSize(default 0): keep-alive connections when idleconnectTimeoutMS: how long to wait for initial connectionserverSelectionTimeoutMS: how long to wait if no server is reachable
For most Node.js web servers, the default pool size of 100 is appropriate. Serverless functions (AWS Lambda) should use smaller pools.
const client = new MongoClient(uri, {
maxPoolSize: 20, // Max 20 simultaneous connections
minPoolSize: 5, // Keep 5 alive when idle
connectTimeoutMS: 5000, // 5s to establish initial connection
serverSelectionTimeoutMS: 5000 // 5s to select a server
});
// The client pool is shared across all operations
// Never create per-request clients!insertOne and insertMany in Node.js
All driver operations return Promises. Use async/await for clean, readable code. The insert methods accept documents as plain JavaScript objects—the driver automatically serializes them to BSON.
The result objects include acknowledged (boolean) and insertedId/insertedIds. TypeScript users can pass a generic type parameter to get typed documents: db.collection<User>('users').
const db = client.db('shop');
const products = db.collection('products');
// insertOne
const { insertedId } = await products.insertOne({
name: 'Wireless Mouse',
price: 29.99,
stock: 150,
createdAt: new Date()
});
console.log('Inserted product:', insertedId);
// insertMany
const { insertedCount } = await products.insertMany([
{ name: 'Keyboard', price: 49.99, stock: 80 },
{ name: 'Monitor', price: 299.99, stock: 25 }
]);
console.log('Inserted:', insertedCount);findOne in Node.js
collection.findOne(filter, options) returns a Promise that resolves to the matching document or null. The optional options object accepts projection, sort, and maxTimeMS.
A common pattern in web APIs: look up a resource by its URL parameter (the id string), convert it to an ObjectId for the query, and return 404 if null is returned. Always validate that the id string is a valid ObjectId format before constructing one—invalid strings throw synchronously.
const { ObjectId } = require('mongodb');
// Express route handler example
app.get('/products/:id', async (req, res) => {
let objId;
try {
objId = new ObjectId(req.params.id);
} catch {
return res.status(400).json({ error: 'Invalid product id' });
}
const product = await db.collection('products').findOne(
{ _id: objId },
{ projection: { name: 1, price: 1, stock: 1, _id: 0 } }
);
if (!product) return res.status(404).json({ error: 'Not found' });
res.json(product);
});find() and Cursor in Node.js
In Node.js, collection.find(filter, options) returns a FindCursor. You iterate it with for await...of, call .toArray() to load all results, or use .forEach(callback). All options (sort, limit, skip, projection) can be passed in the options object or chained as methods.
For API list endpoints, .toArray() is convenient—just ensure you always apply .limit(n) to prevent loading unbounded result sets. For data processing jobs (exports, migrations), stream with for await...of.
// List endpoint with pagination
app.get('/products', async (req, res) => {
const page = parseInt(req.query.page) || 1;
const limit = 20;
const skip = (page - 1) * limit;
const products = await db.collection('products')
.find({ stock: { $gt: 0 } })
.sort({ price: 1 })
.skip(skip)
.limit(limit)
.project({ name: 1, price: 1, _id: 1 })
.toArray();
res.json({ page, products });
});Error Handling Patterns
All driver operations can throw errors: network issues, authentication failures, write conflicts, validation errors. Use try/catch around all database calls in production code. Key error types:
MongoNetworkError: connectivity problem—retry logic may helpMongoServerErrorcode11000: duplicate key violationMongoServerErrorcode121: document failed schema validation
Build a withRetry wrapper for transient network errors. Do not retry validation or duplicate key errors—they indicate a logic bug, not a transient failure.
async function createUser(data) {
try {
const result = await db.collection('users').insertOne(data);
return { id: result.insertedId };
} catch (err) {
if (err.code === 11000) {
// Duplicate email
throw new Error('EMAIL_IN_USE');
}
if (err.code === 121) {
// Schema validation failed
throw new Error('INVALID_DATA');
}
// Network or other error - let it propagate
throw err;
}
}Handling ObjectId in API Responses
When returning MongoDB documents in a REST API response, ObjectId objects are serialized to a string representation by JSON.stringify, appearing as '64a2f3b1c9e7e12345678901'. Clients then send this string back as the ID in subsequent requests.
A common pattern is to transform documents in a mapping function: convert _id to id as a string, removing the MongoDB-specific underscore prefix that clients may find confusing. This also avoids leaking internal MongoDB implementation details to API consumers.
// Transform MongoDB document for API response
function toPublicUser(doc) {
const { _id, passwordHash, ...rest } = doc;
return {
id: _id.toString(), // ObjectId -> string
...rest // All other fields, minus passwordHash
};
}
const user = await db.collection('users').findOne({ email });
if (user) res.json(toPublicUser(user));
// Client sends 'id' string back:
// GET /users/64a2f3b1c9e7e12345678901
// Server converts: new ObjectId(req.params.id)Sharing the Client Across Modules
The recommended Node.js pattern is to initialize MongoClient once and share it across modules using a singleton pattern or dependency injection. A common approach is a db.js module that exports a connectDB() function and a getDB() accessor.
Call connectDB() once at application startup (in server.js or app.js). All route handlers and service modules call getDB() to get the database reference without creating new connections.
// db.js - singleton pattern
const { MongoClient } = require('mongodb');
let db;
async function connectDB() {
const client = new MongoClient(process.env.MONGODB_URI);
await client.connect();
db = client.db('myapp');
console.log('MongoDB connected');
}
function getDB() {
if (!db) throw new Error('DB not initialized - call connectDB() first');
return db;
}
module.exports = { connectDB, getDB };
// Usage in a route:
// const { getDB } = require('./db');
// const db = getDB();
// await db.collection('users').find({}).toArray();Graceful Shutdown
When your Node.js process receives a shutdown signal (SIGTERM, SIGINT), close the MongoClient gracefully with client.close(). This flushes pending write buffers, closes open cursors, and releases TCP connections cleanly.
Without graceful shutdown, MongoDB may see an abrupt disconnection, trigger error handling on in-flight operations, and the connection pool on the server side remains open until the idle timeout fires. In high-traffic systems, many abrupt shutdowns can exhaust MongoDB's connection limit.
// Graceful shutdown handlers
const client = new MongoClient(uri);
await client.connect();
process.on('SIGINT', async () => {
console.log('Shutting down...');
await client.close();
process.exit(0);
});
process.on('SIGTERM', async () => {
console.log('Received SIGTERM');
await client.close();
process.exit(0);
});
// Express:
const server = app.listen(3000);
process.on('SIGTERM', () => server.close(async () => {
await client.close();
}));TypeScript Integration
The MongoDB Node.js driver includes first-class TypeScript support. You can define an interface for your document shape and pass it as a generic to db.collection<MyType>(). The driver then provides type-safe results for findOne, find().toArray(), and more.
One subtlety: the TypeScript type must include _id?: ObjectId to match what MongoDB returns. When projecting out _id, TypeScript still includes it in the type—you may want to use WithId<T> or define separate input and output types for a fully type-safe implementation.
import { MongoClient, ObjectId } from 'mongodb';
// Define your document interface
interface User {
_id?: ObjectId;
name: string;
email: string;
age: number;
createdAt: Date;
}
const users = db.collection<User>('users');
// Fully typed result
const user = await users.findOne({ email: 'alice@test.com' });
// user is User | null
if (user) console.log(user.name.toUpperCase()); // TypeScript knows name is stringQuick Check
Test your understanding of MongoDB & NoSQL Databases concepts from this lesson.
Lesson Recap
In this lesson you learned: MongoClient manages a connection pool—create one instance at startup and share it across all modules to avoid connection overhead, all operations return Promises and should be awaited with try/catch for proper error handling, with error code 11000 indicating duplicate key violations, and TypeScript generics on collection<T>() provide type-safe document access with full IDE support. Next up we explore MongoDB's full suite of comparison and logical query operators to write precise, complex filters.
Pertanyaan yang Sering Diajukan
Apakah pelajaran “Membaca Dokumen dengan Driver Node.js” gratis?
Ya — teks lengkap “Membaca Dokumen dengan Driver Node.js” gratis dibaca di sini di web. Untuk praktiknya secara interaktif (editor kode bawaan dan tutor AI 24/7) dan buka sisa kursus MongoDB Academy, upgrade ke CoddyKit PRO. Kursus MongoDB Academy mencakup 4 pelajaran total.
Apa yang akan aku pelajari di “Membaca Dokumen dengan Driver Node.js”?
Hubungkan skrip Node.js ke MongoDB dan lakukan operasi insert/find menggunakan driver resmi. Kamu berlatih MongoDB Academy dengan kode praktik yang langsung kamu jalankan di browser, dan tutor AI 24/7 menjawab pertanyaanmu saat kamu mengerjakan pelajaran ini.
Apakah aku perlu pengalaman untuk memulai MongoDB Academy?
Tidak diperlukan pengalaman sebelumnya. MongoDB Academy di CoddyKit dirancang untuk pemula hingga pelajar tingkat lanjut, jadi kamu bisa memulai di sini atau dari awal dan belajar sesuai kecepatan kamu sendiri. Ini adalah pelajaran 4 dari 4.
Berapa lama pelajaran “Membaca Dokumen dengan Driver Node.js” memakan waktu?
Sebagian besar pelajaran CoddyKit memakan waktu sekitar 5–10 menit. Setiap pelajaran ringkas dan interaktif, jadi kamu membuat kemajuan stabil dan melanjutkan dari tempat kamu tinggalkan di web dan aplikasi.
Bisakah aku menulis dan menjalankan kode dalam pelajaran MongoDB Academy ini?
Ya. Setiap pelajaran MongoDB Academy menyertakan editor kode bawaan, jadi kamu menulis dan menjalankan kode nyata langsung di browser dan mendapatkan umpan balik AI instan — tidak diperlukan penyiapan lokal.
Semua pelajaran dalam kursus ini
- insertOne dan insertMany
- findOne vs find: Penjelasan Kursor
- Membuat Kueri Bidang Bertingkat dan Array
- Membaca Dokumen dengan Driver Node.js