Connecting to a Database πΎ
So far, our data has been stored in in-memory arrays, which means it disappears every time the server restarts. Real-world applications need to persist data in a database.
A very common choice for Express applications is MongoDB, a NoSQL document database, paired with Mongoose, an Object Data Modeling (ODM) library.
- MongoDB: Stores data in flexible, JSON-like documents called BSON.
- Mongoose: A library that runs on top of the native MongoDB driver. It simplifies interacting with the database by providing a schema-based structure for your data, input validation, and an elegant API for querying.
The Mongoose Workflow
The general process for using Mongoose in an Express app is:
- Connect to the Database: Establish a connection to your MongoDB server, usually when your application first starts.
- Define a Schema: A schema is a blueprint that defines the structure of the documents within a collection. It specifies data types, default values, and validators.
- Create a Model: A model is a constructor compiled from a schema. You use the model to perform CRUD (Create, Read, Update, Delete) operations on the database collection.
π» Example: Refactoring a CRUD API with Mongoose
Letβs refactor our simple βitemsβ API from the routing lesson to use MongoDB and Mongoose. This example assumes you have a running MongoDB instance.
app.js
const express = require("express");
const mongoose = require("mongoose");
const app = express();
app.use(express.json());
// 1. CONNECT TO MONGODB
const mongoURI = "mongodb://127.0.0.1:27017/my-express-db"; // Replace if using a different host
mongoose
.connect(mongoURI)
.then(() => console.log("MongoDB connected successfully."))
.catch((err) => console.error("MongoDB connection error:", err));
// 2. DEFINE A SCHEMA
const itemSchema = new mongoose.Schema({
name: { type: String, required: true },
createdAt: { type: Date, default: Date.now },
});
// 3. CREATE A MODEL
const Item = mongoose.model("Item", itemSchema);
// --- ROUTES ---
// READ: Get all items
app.get("/items", async (req, res) => {
try {
const items = await Item.find(); // Mongoose method to find all documents
res.json(items);
} catch (err) {
res.status(500).json({ error: err.message });
}
});
// CREATE: Add a new item
app.post("/items", async (req, res) => {
try {
const newItem = new Item({ name: req.body.name });
await newItem.save(); // Mongoose method to save a new document
res.status(201).json(newItem);
} catch (err) {
res.status(400).json({ error: err.message });
}
});
// UPDATE: Update an existing item
app.put("/items/:id", async (req, res) => {
try {
const updatedItem = await Item.findByIdAndUpdate(
req.params.id,
{ name: req.body.name },
{ new: true } // Option to return the updated document
);
if (!updatedItem) return res.status(404).json({ error: "Item not found" });
res.json(updatedItem);
} catch (err) {
res.status(400).json({ error: err.message });
}
});
// DELETE: Delete an item
app.delete("/items/:id", async (req, res) => {
try {
const deletedItem = await Item.findByIdAndDelete(req.params.id);
if (!deletedItem) return res.status(44).json({ error: "Item not found" });
res.status(204).send(); // No content
} catch (err) {
res.status(500).json({ error: err.message });
}
});
app.listen(3000, () => console.log("Server is running on port 3000"));β¨ Summary
- Real applications require a database to persist data between server restarts.
- MongoDB is a popular NoSQL database, and Mongoose is an ODM library that makes it easy to work with MongoDB in a Node.js environment.
- The core Mongoose workflow is to Connect, define a Schema (the blueprint), and create a Model (the tool for interaction).
- You use Mongoose model methods (like
.find(),.save(),.findByIdAndUpdate()) inside your Express route handlers to perform CRUD operations. - These methods are asynchronous and integrate perfectly with modern
async/awaitsyntax.
Last updated on