In today’s lesson, we will learn how to ensure the data we work with is correct and how to avoid having the same data more than once in our MongoDB database using Mongoose. This is crucial because making sure our data is accurate and unique helps our applications run smoothly without errors or confusion.
In this lesson, you'll learn:
- How to validate data in
Mongoose
schemas. - How to handle and prevent duplicate entries.
- Practical examples to implement these concepts in a simple web application.
Let's start by setting up an Express.js server and connecting it to our MongoDB instance. This allows us to serve our application and communicate with the database.
JavaScript1const express = require('express'); 2const mongoose = require('mongoose'); 3 4const app = express(); 5const PORT = 3000; 6 7// Set mongoose strictQuery to true to suppress deprecation warning 8mongoose.set('strictQuery', true); 9 10// Connect to MongoDB 11mongoose.connect('mongodb://127.0.0.1:27017/todo-app', { 12 useNewUrlParser: true, 13 useUnifiedTopology: true 14}) 15.then(() => console.log("Connected to MongoDB")) 16.catch((error) => console.error("Failed to connect to MongoDB:", error)); 17 18app.use(express.json());
In this part of the code, we set up an Express.js server and connect to a MongoDB database named todo-app
running on localhost. The useNewUrlParser
and useUnifiedTopology
options are included to avoid deprecation warnings. We also use the express.json()
middleware to parse incoming JSON requests, which is essential for handling JSON payloads in API requests.
Next, let's define schemas for our data models. Schemas in Mongoose act like blueprints for the documents in your collections. This is important because it allows us to enforce a structure on our data and add validation rules.
JavaScript1// Define schema for categories 2const categorySchema = new mongoose.Schema({ 3 name: { type: String, required: true } 4}); 5 6// Define schema for ToDo items with a reference to categories 7const todoSchema = new mongoose.Schema({ 8 task: { type: String, required: true }, 9 category: { type: mongoose.Schema.Types.ObjectId, ref: 'Category' } 10});
In this part of the code, we define two schemas using Mongoose: one for categories and one for ToDo items. The categorySchema
has a single field name
which is required. The todoSchema
has a task
field which is a string and is required, and a category
field which is a reference to a Category
document. These schemas help ensure that every document in the respective collections follows a defined structure and validation rules.
After defining the schemas, we need to create models from them. Models are constructors that let us create instances of our defined schema types.
JavaScript1// Create models 2const Category = mongoose.model('Category', categorySchema); 3const Todo = mongoose.model('Todo', todoSchema);
Here, we create models for both categories and ToDo items. Category
and Todo
are now Mongoose models that we can use to interact with their respective collections in the MongoDB database. They provide methods to perform CRUD (Create, Read, Update, Delete) operations on the data.
Next, let’s create a route to handle adding new ToDo items. We will validate the task field and check for duplicate entries to ensure data integrity.
JavaScript1// Route to create a new ToDo item with validation 2app.post('/add-todo', async (req, res) => { 3 const { task, categoryId } = req.body; 4 5 // Validate task 6 if (!task) { 7 return res.status(400).json({ message: 'Task is required' }); 8 } 9 10 // Check for duplicate entries 11 const existingTodo = await Todo.findOne({ task }); 12 if (existingTodo) { 13 return res.status(400).json({ message: 'Duplicate task' }); 14 } 15 16 const newTodo = new Todo({ 17 task, 18 category: categoryId 19 }); 20 21 try { 22 const savedTodo = await newTodo.save(); 23 res.status(201).json(savedTodo); 24 } catch (error) { 25 res.status(500).json({ message: 'Failed to create todo' }); 26 } 27});
In this route, we handle POST requests to /add-todo
to create new ToDo items. We extract the task and category ID from the request body. First, we validate that the task field is not empty; if it is, we respond with a 400 status code and a relevant error message. Next, we check for existing ToDo items with the same task. If a duplicate is found, we return a "Duplicate task" error. If everything is in order, we create a new Todo
document with the provided task and categoryId, save it to the database, and return the saved document in the response.
To make our application accessible, we need to start the Express server.
JavaScript1app.listen(PORT, () => { 2 console.log(`Server running on http://localhost:${PORT}`); 3});
Here, we instruct the Express application to listen on the specified port (3000 in this case). When the server is running, it will log a message indicating the URL where it's accessible.
In this lesson, we covered how to ensure our data is valid and how to handle duplicate entries in MongoDB
using Mongoose
. Validating data ensures everything we save is complete and meaningful, while handling duplicates keeps our data unique and tidy. Now, you can move on to the practice exercises where you will apply these concepts yourself. Remember, practicing is key to understanding and mastering these skills. Happy coding!