Applications talk to MongoDB through a driver, and connection handling mistakes are a classic production bug.
Install the driver with npm install mongodb. A MongoClient manages a connection pool; create one per process at startup and reuse it everywhere. Opening a new client per request exhausts connections and adds latency.
client.db("shop").collection("orders") gives you a collection object with the same methods as the shell: insertOne, find, updateMany, aggregate, createIndex... Every operation returns a Promise, so use await. find returns a cursor: call .toArray() for small results or iterate with for await (const doc of cursor) to stream large ones.
Differences from mongosh worth knowing:
- import types from the package:
import { MongoClient, ObjectId } from "mongodb", and convert string ids withnew ObjectId(id)before querying_id, - numbers in JavaScript are doubles; use
LongorDecimal128when you need exact integers beyond 2^53 or money, - results of
insertOneetc. are plain objects like{ acknowledged, insertedId }.
Keep the connection string (with credentials) in an environment variable, not in code. Call client.close() on shutdown. With TypeScript, db.collection<Order>("orders") types documents. ODMs such as Mongoose add schemas and validation on top of the driver.
Example
import { MongoClient, ObjectId } from "mongodb";
const client = new MongoClient(process.env.MONGODB_URI ?? "mongodb://localhost:27017");
const orders = client.db("shop").collection("orders"); // reuse these everywhere
async function main() {
const { insertedId } = await orders.insertOne({ customer: "ana", total: 12.5 });
const doc = await orders.findOne({ _id: new ObjectId(insertedId.toString()) });
console.log(doc.total); // 12.5
for await (const o of orders.find({ total: { $gt: 10 } }).sort({ total: -1 })) {
console.log(o.customer); // ana
}
const res = await orders.updateMany({ customer: "ana" }, { $set: { vip: true } });
console.log(res.modifiedCount); // 1
}
main().finally(() => client.close());Remember
- One MongoClient per process: it is a connection pool
- Every operation returns a Promise; cursors support for await
- Convert string ids with new ObjectId(id) before matching _id
- Keep the URI in an environment variable
Watch out for
- Creating a new MongoClient for each HTTP request.