Lesson 2
Defining Mongoose Schemas and Models
Introduction

In this lesson, we'll dive into the practical aspects of using Mongoose with Express to create and view a todo item via an API. By the end of this lesson, you'll know how to define a Mongoose schema and model, create a sample todo item, and view it.

What You'll Learn

In this lesson you'll learn:

  • How to set up an Express server with Mongoose.
  • How to define a Mongoose schema and model with additional fields.
  • How to create a sample todo item.
  • How to view the created todo items via the API.
Step 1: Importing Libraries and Setting Up Express Server

We'll start by importing the required libraries, initializing our Express application, and setting up middleware to parse JSON request bodies.

JavaScript
1const express = require('express'); 2const mongoose = require('mongoose'); 3 4const app = express(); 5 6// Middleware to parse JSON request bodies 7app.use(express.json());

Here, we:

  1. Import express and mongoose.
  2. Create an Express application instance.
  3. Use middleware to allow our Express application to understand and parse JSON bodies from incoming requests.
Step 2: Connecting to MongoDB

Next, we'll establish a connection to our MongoDB database.

JavaScript
1// Set mongoose strictQuery to true to suppress deprecation warning 2mongoose.set('strictQuery', true); 3 4mongoose.connect('mongodb://127.0.0.1:27017/todo-app', { 5 useNewUrlParser: true, 6 useUnifiedTopology: true, 7}) 8.then(() => console.log("Connected to MongoDB")) 9.catch((error) => console.error("Failed to connect to MongoDB:", error));

This code:

  1. Connects to a MongoDB database named todo-app running locally.
  2. Logs a success message upon successful connection.
  3. Catches and logs any connection errors.
Step 3: Defining Mongoose Schema and Model

Now, let's create a schema and a model for our todo items.

JavaScript
1const todoSchema = new mongoose.Schema({ 2 task: { type: String, required: true }, 3 status: { type: String, required: true } 4}); 5 6const Todo = mongoose.model('Todo', todoSchema);

Here we:

  1. Define a schema with two fields: task, which is a required string, and status, which is also a required string.
  2. Create a Todo model from the schema, which we will use to interact with the todos collection in MongoDB.

Understanding Automatically Added Fields: _id and __v:

Mongoose automatically adds some fields to each document, which you may notice in the API responses:

  • _id: Mongoose adds an _id field to each document, which uniquely identifies the document within the collection. This is similar to a primary key in a relational database and is essential for distinguishing individual documents.
  • __v: Mongoose also adds a __v field to track the version of the document. This is useful for handling concurrency and ensuring that updates to documents are applied correctly.

Now, let's move on to creating API routes to handle creating and viewing todo items.

Step 4: Creating a Sample Todo Item via API Route

To ensure our schema and model work correctly, let's create an API route to handle the creation of todo items.

JavaScript
1app.post('/todos', async (req, res) => { 2 try { 3 const { task, status } = req.body; 4 const newTodo = new Todo({ 5 task, 6 status: status || 'In Progress' 7 }); 8 const savedTodo = await newTodo.save(); 9 res.status(201).send(savedTodo); 10 } catch (err) { 11 res.status(400).send({ error: 'Error creating Todo: ' + err.message }); 12 } 13});

In this snippet:

  1. We define a POST route /todos to create new todo items.
  2. Extract task and status from the request body.
  3. Create a new Todo document with the task description and status, defaulting to "In Progress" if no status is provided.
  4. Attempt to save the new document to the database.
  5. If successful, we send the created todo item back to the client with a 201 status code.
  6. If there's an error, we catch it and respond with a 400 status code and an error message.
Step 5: Viewing Todo Items via API Route

Next, let's create an API route to get all todo items.

JavaScript
1app.get('/todos', async (req, res) => { 2 try { 3 const todos = await Todo.find(); 4 res.status(200).send(todos); 5 } catch (err) { 6 res.status(400).send({ error: 'Error fetching Todos: ' + err.message }); 7 } 8});

In this snippet:

  1. We define a GET route /todos to retrieve all todo items from the database.
  2. Attempt to find all documents in the todos collection.
  3. If successful, we send the retrieved todo items back to the client with a 200 status code.
  4. If there's an error, we catch it and respond with a 400 status code and an error message.
Step 6: Starting the Express Server

Finally, we start the server and listen on the defined port.

JavaScript
1const port = process.env.PORT || 3000; 2 3app.listen(port, () => { 4 console.log(`Server listening on port ${port}`); 5}); 6 7// Export the model (optional, useful for importing in other files) 8module.exports = Todo;

This code starts the Express server and logs a message indicating that the server is running. To make the model available for import in other files, we need to export it.

Conclusion

In this lesson, we learned how to set up an Express server with Mongoose, define a schema and model with additional fields, create a sample todo item via an API route, and view the created todo items via another API route. By following these steps, you can effectively manage your data using Mongoose and expose functionality through a RESTful API.

Enjoy this lesson? Now it's time to practice with Cosmo!
Practice is how you turn knowledge into actual skills.