Node Driver and Mongoose (Optional)
Introduction
Node.js talks to MongoDB through the official mongodb driver (low level) or Mongoose (schema, middleware, population). This optional chapter shows both with a small blog API and links to Node database basics without repeating npm fundamentals.
Prerequisites
- npm and package.json
- Async/await in JavaScript
- BSON and Document Basics
- MongoDB running locally or Atlas URI
Install
Official driver:
npm install mongodbMongoose (ODM):
npm install mongooseOfficial Driver: MongoClient
db.mjs:
Express route:
Code explanation:
ObjectId.isValidbefore constructingObjectId— avoids exceptions and injection-style bugs — Security- Reuse one
MongoClientper process (module singleton), not per request
Mongoose: Schema and Model
models/post.js:
Connect once at startup:
await mongoose.connect(process.env.MONGODB_URI ?? "mongodb://127.0.0.1:27017/hello_demo");Create and query:
const post = await Post.create({
title: "Mongoose Intro",
slug: "mongoose-intro",
published: true,
tags: ["nodejs", "mongodb"],
});
const list = await Post.find({ published: true })
.sort({ createdAt: -1 })
.limit(20)
.select("title slug createdAt")
.lean();.lean() returns plain objects—faster read-only APIs.
Population (References)
models/comment.js:
const commentSchema = new mongoose.Schema({
postId: { type: mongoose.Schema.Types.ObjectId, ref: "Post", required: true },
author: String,
body: String,
createdAt: { type: Date, default: Date.now },
});
export const Comment = mongoose.model("Comment", commentSchema);const comments = await Comment.find({ postId: post._id })
.sort({ createdAt: 1 })
.populate("postId", "title slug");Population runs extra queries—at scale prefer aggregation $lookup — chapter 13.
Middleware Example
postSchema.pre("save", function (next) {
if (this.isModified("slug")) {
this.slug = this.slug.toLowerCase().trim();
}
next();
});Hooks replace some app-layer validation; DB validator still helps — Schema Validation.
Driver vs Mongoose
| Layer | Best for |
|---|---|
mongodb driver | Full control, microservices, aggregation-heavy pipelines |
| Mongoose | CRUD apps, schema enforcement, hooks, quick REST APIs |
Tip
Team choice
Pick Mongoose when the team wants schema docs in code. Pick the native driver when you mirror PyMongo-style dict queries or need minimal abstraction.
FAQ
TypeScript?
Use @types/mongoose or Mongoose 7+ built-in types; driver ships TypeScript definitions.
Next.js API routes?
Connect in a shared module; avoid connecting per request in serverless—use connection pooling patterns or Atlas serverless limits.
Validation vs MongoDB validator?
Mongoose validates before send; MongoDB validator is server-side backup — chapter 14.
Fastify instead of Express?
Same driver/Mongoose—swap HTTP layer only.
Compare Python track?
PyMongo Basics and FastAPI integration cover the same CRUD patterns in Python.