Introduction
Welcome back! In the last lesson, you successfully created and mounted a dedicated Express router for your item-related endpoints. This established a clean, scalable foundation for your API. Your GET /api/items route currently sends a simple text response, acting as a placeholder.
In this lesson, you will bring that endpoint to life. You will replace the placeholder with the actual logic to fetch all item records from your MongoDB database. To do this, you'll use the Mongoose Model.find() method. Since database operations are asynchronous, you'll leverage your existing knowledge of async/await to handle them cleanly, including basic error handling.
By the end of this lesson, you will have implemented your first fully functional CRUD operation: Read (all resources).
1. The Core Pattern: Model.find()
Your Item model, which you created earlier, is not just a schema definition; it's a powerful interface to your items collection in MongoDB. Mongoose provides several static methods on the model to perform database operations.
To retrieve all documents from the collection, you will use the find() method.
Model.find(): When called with no arguments or an empty object ({}), this method queries the database for every document in the model's collection.- Asynchronous Nature: Like all database operations,
find()is asynchronous. It returns a MongooseQueryobject, which is "thenable"—meaning you can useawaitwith it to wait for the database results.
The standard, production-ready pattern for this operation is to wrap the await call in a try...catch block. This ensures that if the database connection fails or another server-side error occurs, your application won't crash and can instead send a meaningful error response to the client.
2. Implementation: The "Get All" Route
It's time to replace the placeholder route in src/routes/item.routes.js.
First, you need to import your Item model so you can use it within the route file. Then, you'll rewrite the route handler to be an async function and implement the try...catch logic.
Action: Open src/routes/item.routes.js and update its content to the following:
const express = require('express');
const router = express.Router();
// 1. Import the Item model
const Item = require('../models/item.model.js');
// This was your placeholder route:
// router.get('/', (req, res) => {
// res.send('Items route is working!');
// });
// 2. Replace it with the new implementation
// @route GET /api/items
// @desc Get all items
// @access Public
router.get('/', async (req, res) => {
try {
const items = await Item.find(); // Fetches all documents from the Item collection
res.status(200).json(items); // Sends the items back as a JSON array with a 200 OK status
} catch (error) {
// If an error occurs on the server (e.g., database connection issue)
res.status(500).json({ message: "Failed to retrieve items", error: error.message });
}
});
module.exports = router;
Code Breakdown:
async (req, res): Declares that this route handler will perform asynchronous operations.try { ... }: The "happy path." We attempt to query the database and send a successful response.await Item.find(): This is the core command. It tells Mongoose to fetch all documents and pauses execution until the data is returned or an error occurs.res.status(200).json(items): If successful, we send back an HTTP status code200 OKand the array of items in the response body.catch (error) { ... }: The "error path." Ifawait Item.find()throws an error, thecatchblock executes.res.status(500).json(...): We send back an HTTP status code500 Internal Server Errorto indicate the problem was on our end, not the client's.
3. Guided Walkthroughs
To see this exact pattern implemented in real-time, the following resources are extremely useful. They demonstrate the same concepts with slightly different models, reinforcing the universal nature of this pattern.
First, this video provides a very quick and direct implementation.
Build A REST API With Node.js, Express, & MongoDB - Quick
The video 'Build A REST API With Node.js, Express, & MongoDB - Quick' by Web Dev Simplified demonstrates the exact pattern we just implemented. Pay close attention to the use of async/await, try/catch, and the Subscriber.find() method.
Watch from 14:18 to 16:08. The presenter implements a 'get all' route for a Subscriber model, which is conceptually identical to our Item model route.
For a text-based alternative that you can quickly reference, this article provides a clean code snippet.
Integrating MongoDB with Mongoose
The article 'Integrating MongoDB with Mongoose' from CodeSignal Learn has a section that shows a clear, concise code block for retrieving all documents.
Read the short section titled 'Retrieving All Todos'. Notice how their code for fetching all Todo items is structured exactly like our code for fetching all Items.
4. Testing Your Endpoint
With your updated code, it's time to verify that it works.
- Start your server from the terminal (
npm run devornpm start). Ensure your server connects to MongoDB without errors. - Open Postman (or a web browser).
- Make a GET request to your endpoint:
http://localhost:5001/api/items(replace5001with your configured port if different).
You should see a 200 OK status code and a JSON response. If you haven't added any data to your database yet, the response will be an empty array []. This is a successful response!
If you were to add items to your database, the response would look something like this:

This endpoint provides the raw data needed to power a user interface, such as a dashboard listing all available products.
Conclusion
Congratulations! You have successfully implemented your first real API endpoint. You've learned the fundamental pattern for retrieving all resources from a MongoDB collection using Express and Mongoose.
Key Takeaways:
- The
Model.find()method is used to retrieve all documents from a collection. - Database operations must be wrapped in a
try...catchblock within anasyncfunction to handle potential errors gracefully. - A successful GET request should return a
200 OKstatus code along with the requested data in JSON format. - A server-side error during data retrieval should result in a
500 Internal Server Errorstatus code.
Next Up:
Fetching a list of all items is useful, but often a user needs to view the details of a single, specific item. In the next lesson, you will implement the GET /api/items/:id route, where you'll learn to use route parameters and the Model.findById() method to retrieve a single document.