How to Create Relationships with Mongoose and Node.JS?
Last Updated :
09 Jun, 2025
Mongoose is a powerful ODM (Object Data Modeling) library for MongoDB and Node.js, allowing developers to define schemas and interact with MongoDB using models. Creating relationships between schemas is important for building complex applications with interrelated data. This article will guide you through setting up and managing relationships with Mongoose in a Node.js application.
Why Are Relationships Important in MongoDB?
Unlike traditional SQL databases, MongoDB is a NoSQL document-oriented database, which stores data in flexible, JSON-like documents. While MongoDB does not enforce relationships like relational databases, Mongoose provides ways to model relationships, helping you keep your data consistent and easy to query.
Two common types of relationships in MongoDB using Mongoose:
- Referencing (Normalization): Storing ObjectId references from one document to another (like foreign keys).
- Embedding (Denormalization): Nesting related documents directly within a parent document.
Steps on How to Create Relationships with Mongoose and Node.JS
Step 1: Create a New Directory
At first create a new directory for your project and navigate into it.
mkdir Your_folder_name
cd Your_folder_name
Step 2: Initialize a New Node.js Project
After that, you have to Initialize a new node project using npm.
npm init -y
Step 3: Install required packages
Then install the the required package using npm.
npm install express mongoose ejs body-parser
Step 4: Project Structure
Folder structureDependencies
"dependencies": {
"body-parser": "^1.20.2",
"ejs": "^3.1.10",
"express": "^4.19.2",
"mongoose": "^8.5.1"
}
}
Step 5: Define Your Mongoose Schemas with Relationships
Let’s say we want to create a simple app with Authors and Books, where each book references an author.
HTML
<!-- views/layout.ejs code... -->
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Mongoose Relations</title>
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Roboto:400,700&display=swap">
<link rel="stylesheet" href="/style.css">
</head>
<body>
<header>
<h1>Mongoose Relations</h1>
<nav>
<ul>
<li class="nav-lists"><a href="/authors">Authors</a></li>
<li class="nav-lists"><a href="/books">Books</a></li>
</ul>
</nav>
</header>
</body>
</html>
HTML
<!-- views/books.ejs code... -->
<%- include('layout') %>
<h2 class="books-heading">Books</h2>
<form action="/books" method="POST">
<label for="title">Title</label>
<input type="text" name="title" id="title" required>
<label for="author">Author</label>
<select name="author" id="author" required>
<% authors.forEach(author=> { %>
<option value="<%= author._id %>">
<%= author.name %>
</option>
<% }) %>
</select>
<button type="submit">Add Book</button>
</form>
<ul class="books-lists">
<% books.forEach(book=> { %>
<li>
<%= book.title %> by <%= book.author.name %>
</li>
<% }) %>
</ul>
HTML
<!-- views/authors.ejs code... -->
<%- include('layout') %>
<h2 class="author-heading">Authors</h2>
<form action="/authors" method="POST">
<label for="name">Name</label>
<input type="text" name="name" id="name" required>
<button type="submit">Add Author</button>
</form>
<ul class="author-lists">
<% authors.forEach(author=> { %>
<li>
<%= author.name %>
</li>
<% }) %>
</ul>
CSS
/* public/style.css code.... */
body,
h1,
h2,
p,
ul {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
font-family: 'Roboto', sans-serif;
background-color: #f4f7f6;
color: #333;
line-height: 1.6;
}
header {
background-color: rgb(29, 231, 29);
color: white;
padding: 15px 0;
text-align: center;
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
}
header h1 {
margin: 0;
font-size: 24px;
font-weight: 400;
}
header nav ul {
list-style: none;
display: flex;
justify-content: center;
padding: 0;
margin: 10px 0 0;
}
.nav-lists {
background: #007bff;
}
header nav ul li {
margin: 0 15px;
}
header nav ul li a {
color: white;
text-decoration: none;
font-size: 16px;
}
header nav ul li a:hover {
text-decoration: underline;
}
.books-heading {
font-size: 22px;
margin-bottom: 20px;
color: #007bff;
padding-bottom: 10px;
margin-left: 35rem;
font-size: 36px;
}
.author-heading {
font-size: 22px;
margin-bottom: 20px;
color: #007bff;
padding-bottom: 10px;
margin-left: 35rem;
font-size: 36px;
}
form {
margin-bottom: 30px;
padding: 20px;
background-color: #e9ecef;
border-radius: 8px;
width: 30vw;
margin-left: 25rem;
}
form label {
display: block;
margin-bottom: 5px;
font-weight: bold;
color: #495057;
}
form input,
form select,
form button {
display: block;
width: 100%;
padding: 10px;
margin-bottom: 15px;
border: 1px solid #ced4da;
border-radius: 4px;
}
form input:focus,
form select:focus {
border-color: #80bdff;
outline: none;
}
form button {
background-color: #007bff;
color: white;
border: none;
cursor: pointer;
transition: background-color 0.3s ease;
}
form button:hover {
background-color: #0056b3;
}
ul {
list-style: none;
padding: 0;
}
ul li {
background-color: #f8f9fa;
border: 1px solid #e9ecef;
margin-bottom: 10px;
padding: 15px;
border-radius: 4px;
font-size: 16px;
display: flex;
justify-content: space-between;
align-items: center;
}
.author-lists {
margin-left: 25rem;
width: 35vw;
}
.author-lists li:nth-child(even) {
background-color: #e9ecef;
}
.books-lists {
margin-left: 25rem;
width: 35vw;
}
.books-lists li:nth-child(even) {
background-color: #e9ecef;
}
JavaScript
// app.js code....
const express = require("express");
const bodyParser = require("body-parser");
const connectDB = require("./database/db");
const app = express();
const PORT = process.env.PORT || 3000;
// Connect to the database
connectDB();
app.set("view engine", "ejs");
app.use(bodyParser.urlencoded({ extended: true }));
app.use(express.static("public"));
const authorRouter = require("./routes/authors");
const bookRouter = require("./routes/books");
app.use("/authors", authorRouter);
app.use("/books", bookRouter);
app.get("/", (req, res) => {
res.redirect("/authors");
});
app.listen(PORT, (err) => {
if (err) {
console.log(err);
} else {
console.log(`Server is running on http://localhost:${PORT}`);
}
});
JavaScript
// routes/authors.js code .....
const express = require("express");
const router = express.Router();
const Author = require("../models/author");
router.get("/", async (req, res) => {
const authors = await Author.find({});
res.render("authors", { authors });
});
router.post("/", async (req, res) => {
const author = new Author({
name: req.body.name,
});
await author.save();
res.redirect("/authors");
});
module.exports = router;
JavaScript
// routes/books.js code .....
const express = require("express");
const router = express.Router();
const Book = require("../models/book");
const Author = require("../models/author");
router.get("/", async (req, res) => {
const books = await Book.find({}).populate("author");
const authors = await Author.find({});
res.render("books", { books, authors });
});
router.post("/", async (req, res) => {
const book = new Book({
title: req.body.title,
author: req.body.author,
});
await book.save();
res.redirect("/books");
});
module.exports = router;
JavaScript
// models/author.js code .....
const mongoose = require('mongoose');
const authorSchema = new mongoose.Schema({
name: {
type: String,
required: true
}
});
module.exports = mongoose.model('Author', authorSchema);
JavaScript
// models/book.js code .....
const mongoose = require('mongoose');
const Schema = mongoose.Schema;
const bookSchema = new Schema({
title: {
type: String,
required: true
},
author: {
type: Schema.Types.ObjectId,
ref: 'Author',
required: true
}
});
module.exports = mongoose.model('Book', bookSchema);
JavaScript
// database/db.js
const mongoose = require('mongoose');
const connectDB = async () => {
try {
await mongoose.connect('mongodb://localhost:27017/mongoose-relations', {
});
console.log('Database is connected');
} catch (err) {
console.error('Error connecting to the database:', err);
process.exit(1);
}
};
module.exports = connectDB;
Step 6: Run Your Application
To run the code write in the command prompt
node app.js
And open a new tab of your browser and type the following command to show the output.
http://localhost:3000/
Output :
Database Output:
Conclusion
In this article, we explored how to create and manage relationships between schemas using Mongoose in a Node.js application. Understanding referencing and using .populate()
enables efficient handling of related data across collections. Properly modeling relationships improves data organization, reduces duplication, and enhances query performance. With these techniques, building complex and scalable MongoDB applications becomes easier and more maintainable.
Similar Reads
How to Use MongoDB and Mongoose with Node.js ? MongoDB is a popular NoSQL database that offers flexibility and scalability, making it an excellent choice for modern applications. Mongoose, a powerful ODM (Object Data Modeling) library, simplifies the interaction between MongoDB and Node.js by providing a schema-based solution for data validation
6 min read
How to Creating Mongoose Schema with an Array of ObjectID In Mongoose, a powerful MongoDB object modeling tool for Node.js, schemas define the structure of documents within a collection. Sometimes, you may need to create a schema with an array of ObjectIDs to represent relationships between documents in different collections. This article will explain how
4 min read
How to Connect to a MongoDB Database Using Node.js MongoDB is a NoSQL database used to store large amounts of data without any traditional relational database table. To connect to a MongoDB database using NodeJS we use the MongoDB library "mongoose". Steps to Connect to a MongoDB Database Using NodeJSStep 1: Create a NodeJS App: First create a NodeJ
4 min read
How to Connect MongoDB with a Node.js Application using MongooseJS Mongoose is a powerful MongoDB object modeling library for Node.js enabling you to easily interact between your Node.js app and MongoDB. In this article we are going to explore how you can connect your Node.js app to MongoDB using MongooseJS. You will learn how to create a connection, specify schema
4 min read
Node.js CRUD Operations Using Mongoose and MongoDB Atlas CRUD (Create, Read, Update, Delete) operations are fundamental in web applications for managing data. Mongoose simplifies interaction with MongoDB, offering a schema-based approach to model data efficiently. MongoDB Atlas is a fully managed cloud database that simplifies the process of setting up, m
8 min read
How to Perform a findOne Operation in MongoDB using Node.js? The findOne operation in MongoDB is used to get a single document from the collection if the given query matches the collection record. While using findOne, if more than one record is there with the exact same match, then it will return the very first one. We will use this operation if we need to fe
4 min read