1. Introduction
In Express.js, a model typically represents the data layer in an MVC (Model-View-Controller) architecture. The model is responsible for interacting with the database, performing CRUD (Create, Read, Update, Delete) operations, and returning the data that will be used by the controllers to serve responses to the client.
1. What is a Model in Express.js?
- Model: Represents the data structure of the application and interacts with the database. The model defines how data is structured, validated, and stored in the database.
- Express is primarily a server-side framework and does not come with a built-in ORM (Object-Relational Mapping), so you typically use an external ORM like Mongoose for MongoDB, or Sequelize for SQL databases.
2. Setting up Express.js
Here’s how to set up a simple Express application with MongoDB and Mongoose (as the ORM for MongoDB) for a model.
Steps:
-
Install Express.js, Mongoose, and other dependencies:
Terminal window npm init -ynpm install express mongoose -
Create the main app file (
app.js
orserver.js
):const express = require('express');const mongoose = require('mongoose');const app = express();const port = 3000;// Connect to MongoDBmongoose.connect('mongodb://localhost:27017/expressdb').then(() => console.log('Connected to MongoDB')).catch(err => console.log('Error connecting to MongoDB:', err));app.listen(port, () => {console.log(`Server running at http://localhost:${port}`);});
3. Using a Database with Express Models (MongoDB + Mongoose)
In a MongoDB environment, you typically use Mongoose to define your models.
Example:
Let’s build a User Model as an example.
-
Install Mongoose (if not installed already):
Terminal window npm install mongoose -
Create a
models/user.js
file:const mongoose = require('mongoose');// Define schema for Userconst userSchema = new mongoose.Schema({name: {type: String,required: true,},email: {type: String,required: true,unique: true,},password: {type: String,required: true,},createdAt: {type: Date,default: Date.now,},});// Create User modelconst User = mongoose.model('User', userSchema);module.exports = User;
4. Building a Basic Model
A model in Express.js defines the structure of your data, interacts with the database, and provides functions to create, read, update, and delete data.
In the example above, we created a User model using Mongoose, which:
- Defines fields (
name
,email
,password
, etc.). - Specifies validation rules (e.g.,
required
,unique
). - Uses a schema to structure how the data will be stored.
5. CRUD Operations with Models
Here’s how to implement basic CRUD operations for the User model.
Create a User (POST Request):
const express = require('express');const User = require('./models/user');const app = express();app.use(express.json()); // For parsing application/json
// POST route to create a new userapp.post('/users', async (req, res) => { try { const user = new User(req.body); await user.save(); res.status(201).json(user); } catch (err) { res.status(400).json({ message: err.message }); }});
Read Users (GET Request):
// GET route to fetch all usersapp.get('/users', async (req, res) => { try { const users = await User.find(); res.json(users); } catch (err) { res.status(500).json({ message: err.message }); }});
// GET route to fetch a single user by IDapp.get('/users/:id', async (req, res) => { try { const user = await User.findById(req.params.id); if (!user) return res.status(404).json({ message: 'User not found' }); res.json(user); } catch (err) { res.status(500).json({ message: err.message }); }});
Update User (PUT Request):
// PUT route to update user detailsapp.put('/users/:id', async (req, res) => { try { const user = await User.findByIdAndUpdate(req.params.id, req.body, { new: true }); if (!user) return res.status(404).json({ message: 'User not found' }); res.json(user); } catch (err) { res.status(400).json({ message: err.message }); }});
Delete User (DELETE Request):
// DELETE route to delete a userapp.delete('/users/:id', async (req, res) => { try { const user = await User.findByIdAndDelete(req.params.id); if (!user) return res.status(404).json({ message: 'User not found' }); res.json({ message: 'User deleted successfully' }); } catch (err) { res.status(500).json({ message: err.message }); }});
6. Validations and Middleware in Models
You can add validation to your schema fields to enforce rules for data consistency.
Example of Adding Validation to the Model:
const userSchema = new mongoose.Schema({ name: { type: String, required: true, }, email: { type: String, required: true, unique: true, validate: { validator: function (v) { return /\S+@\S+\.\S+/.test(v); }, message: props => `${props.value} is not a valid email!`, }, }, password: { type: String, required: true, minlength: [6, 'Password must be at least 6 characters'], },});
Example of Middleware (Pre-Save Hook):
You can also add middleware (like pre-save hooks) to handle certain actions before saving to the database. For instance, you might want to hash the password before saving the user:
const bcrypt = require('bcryptjs');
// Pre-save hook to hash passworduserSchema.pre('save', async function (next) { if (!this.isModified('password')) return next(); this.password = await bcrypt.hash(this.password, 10); next();});
7. Model Associations (Relationships)
If you need to relate multiple models (e.g., one-to-many or many-to-many), you can use references or embedded documents.
Example of One-to-Many Relationship (User to Posts):
You can relate a User to multiple Posts using references in Mongoose.
-
Post Model (
models/post.js
):const mongoose = require('mongoose');const postSchema = new mongoose.Schema({title: {type: String,required: true,},content: {type: String,required: true,},author: {type: mongoose.Schema.Types.ObjectId,ref: 'User',},createdAt: {type: Date,default: Date.now,},});const Post = mongoose.model('Post', postSchema);module.exports = Post; -
Using the Relationship:
- To create a post with a reference to a user:
const user = await User.findOne({ email: 'example@example.com' });const post = new Post({title: 'My First Post',content: 'This is the content.',author: user._id,});await post.save();
- To create a post with a reference to a user:
-
Populating the Reference:
- You can use Mongoose’s
populate
method to fetch related data:const posts = await Post.find().populate('author', 'name email');
- You can use Mongoose’s