Backend 04 - MongoDB

Code SubtleCode Subtle
9 min read

What is MongoDB?

MongoDB is a NoSQL, document-oriented database. Instead of storing data in tables with rows and columns like traditional relational databases (like MySQL or PostgreSQL), MongoDB stores data in flexible, JSON-like documents.

Here’s a quick comparison:

Relational Database (SQL)

MongoDB (NoSQL)

Database

Database

Tables

Collections

Rows

Documents

Columns

Fields

Key Advantages for Web Development:

  • Flexibility: Since documents are schema-less (or have a flexible schema), you can store documents with varying structures in the same collection. This is great for evolving applications.

  • Scalability: MongoDB is designed to scale out horizontally, meaning you can distribute your data across multiple servers easily.

  • Performance: It's fast, especially for read/write operations involving large amounts of data.

  • JSON-like Documents: Data is stored in BSON (Binary JSON), which maps directly to objects in JavaScript. This makes working with data in a Node.js environment incredibly intuitive.


What is a Model in MongoDB (via Mongoose)?

When working with MongoDB in a Node.js environment, you'll almost always use a library called Mongoose. Mongoose is an Object Data Modeling (ODM) library that provides a straightforward, schema-based solution to model your application data.

A Mongoose Model is essentially a wrapper for a MongoDB collection that provides a structured interface for creating, querying, updating, and deleting documents.

  • Schema: The foundation of a model is its schema. A schema defines the structure of the documents within a collection—specifying the fields, their data types (e.g., String, Number, Date), default values, and validation rules.

  • Model: Once you have a schema, you compile it into a Model. This model maps directly to a collection in your MongoDB database and is the primary tool you'll use to interact with that data.

For example, if you have a users collection in your database, you would create a User model in your application to handle all operations related to users.

Basic Example of a Mongoose Model:

JavaScript

const mongoose = require('mongoose');

// 1. Define the Schema
const userSchema = new mongoose.Schema({
  name: {
    type: String,
    required: true
  },
  email: {
    type: String,
    required: true,
    unique: true
  },
  age: Number,
  createdAt: {
    type: Date,
    default: Date.now
  }
});

// 2. Compile the Schema into a Model
const User = mongoose.model('User', userSchema);

module.exports = User;

Tools Overview: MongoDB Atlas vs. MongoDB Compass

You have several ways to host and interact with your MongoDB database. The two most common tools are MongoDB Atlas (for hosting) and MongoDB Compass (for interacting).

MongoDB Atlas ☁️

Atlas is MongoDB's official cloud-hosted Database-as-a-Service (DBaaS). It handles all the complexity of deploying, managing, and scaling your database, allowing you to focus on your application.

  • When to use it: It's the standard for production applications, team collaboration, or any project where you need reliability, automatic backups, and easy scalability without managing servers yourself.

  • Key Features:

    • Fully managed cloud hosting (on AWS, Google Cloud, or Azure).

    • Automated backups and point-in-time recovery.

    • Advanced security features and monitoring tools.

    • Simple connection strings to link to your application.

MongoDB Compass 🧭

Compass is a GUI (Graphical User Interface) that allows you to visually interact with your MongoDB data. It’s like a browser for your database.

  • When to use it: It's perfect for local development, data visualization, debugging, and running queries without writing code.

  • Key Features:

    • Visually explore your databases, collections, and documents.

    • Create, read, update, and delete documents with a user-friendly interface.

    • Analyze your schema to understand your data structure.

    • Build and optimize queries with a visual query builder.

Comparison: Atlas vs. Compass

Feature

MongoDB Atlas

MongoDB Compass

Purpose

Database Hosting (Cloud DB)

Database GUI (Client)

Use Case

Production, Staging, Team Dev

Local Development, Debugging

Environment

Cloud-based (requires internet)

Desktop application

Primary Job

To store and manage your data.

To view and interact with your data.

In short: You host your database on Atlas and can use Compass to connect to it.


Setting Up MongoDB Atlas and Connecting to Express

Let's get our hands dirty! Here’s a step-by-step guide to setting up a free database on Atlas and connecting it to an Express app.

Step 1: Sign Up on MongoDB Atlas Go to the MongoDB Atlas website and create a free account.

Step 2: Create a Cluster A cluster is a group of servers that host your data.

  • After signing up, create a new project.

  • Click "Build a Database".

  • Choose the Shared (M0) tier, which is free forever and perfect for learning.

  • Select a cloud provider and region (choose one close to you).

  • Name your cluster (e.g., MyTestCluster) and click "Create".

Step 3: Add a Database User and Whitelist IP Address You need to create credentials to access the database and grant network permission.

  • In your cluster's dashboard, go to Database Access.

  • Click Add New Database User. Enter a username and a secure password. Remember these credentials!

  • Next, go to Network Access.

  • Click Add IP Address. For development, you can click Allow Access from Anywhere (which adds 0.0.0.0/0). For production, you should add the specific IP address of your server.

Step 4: Get Your Connection String This is the unique address (URI) your application will use to connect to the database.

  • In your cluster's dashboard, go to Database.

  • Click the Connect button for your cluster.

  • Select Connect your application.

  • Choose Node.js as your driver and the latest version.

  • Your connection string will be displayed. Click Copy. It will look something like this: mongodb+srv://<username>:<password>@mytestcluster.xxxxx.mongodb.net/?retryWrites=true&w=majority

Step 5: Connect to Your Express App Now, let's use this in our Express project.

  1. Install dependencies:

    Bash

     npm install express mongoose dotenv
    
  2. Set up your .env file (see Best Practices section below for more details): Create a file named .env in your project root and add your connection string. Replace <username> and <password> with the credentials you created in Step 3.

     MONGO_URI=mongodb+srv://myuser:mypassword123@mytestcluster.xxxxx.mongodb.net/myFirstDatabase?retryWrites=true&w=majority
    

    Note: You can specify a database name in the URI (e.g., myFirstDatabase). If it doesn't exist, MongoDB will create it on the first connection.

  3. Write the connection code in your index.js or server.js:

    JavaScript

     require('dotenv').config(); // Load environment variables
     const express = require('express');
     const mongoose = require('mongoose');
    
     const app = express();
     const PORT = process.env.PORT || 3000;
    
     // --- MongoDB Connection ---
     mongoose.connect(process.env.MONGO_URI, {
       useNewUrlParser: true,
       useUnifiedTopology: true
     })
     .then(() => {
       console.log('✅ MongoDB connected successfully!');
       // Start the server only after the database connection is successful
       app.listen(PORT, () => {
         console.log(`🚀 Server is running on port ${PORT}`);
       });
     })
     .catch(err => {
       console.error('❌ MongoDB connection error:', err);
       process.exit(1); // Exit the process with a failure code
     });
    
     // Simple test route
     app.get('/', (req, res) => {
         res.send('Hello World!');
     });
    

Now, run your server (node index.js), and you should see the success message in your console!


Creating Models and Using Them in Express

Once connected, you can start defining models and using them in your API routes to perform CRUD (Create, Read, Update, Delete) operations.

Let's create a simple To-Do application.

1. Define the Schema and Model (models/Todo.js)

JavaScript

const mongoose = require('mongoose');

const todoSchema = new mongoose.Schema({
  task: {
    type: String,
    required: true,
  },
  completed: {
    type: Boolean,
    default: false,
  },
});

const Todo = mongoose.model('Todo', todoSchema);

module.exports = Todo;

2. Create Routes in index.js to Use the Model

JavaScript

// ... (previous connection code) ...
const Todo = require('./models/Todo'); // Import the model

// Middleware to parse JSON bodies
app.use(express.json());

// --- API Routes ---

// CREATE a new todo
app.post('/todos', async (req, res) => {
  try {
    const newTodo = new Todo({
      task: req.body.task,
    });
    const savedTodo = await newTodo.save();
    res.status(201).json(savedTodo);
  } catch (error) {
    res.status(400).json({ message: error.message });
  }
});

// READ all todos
app.get('/todos', async (req, res) => {
  try {
    const todos = await Todo.find();
    res.json(todos);
  } catch (error) {
    res.status(500).json({ message: error.message });
  }
});

// ... add routes for UPDATE and DELETE similarly ...

Using MongoDB Compass for Development

Compass makes it easy to check if your data is being saved correctly.

  1. Install: Download and install MongoDB Compass.

  2. Connect: Open Compass and click "New Connection". Paste the same MongoDB Atlas connection string you used in your Express app. Compass will automatically parse it, you just need to confirm the details and click "Connect".

  3. Browse: Once connected, you will see your databases on the left. Click on your database (e.g., myFirstDatabase), then your collection (todos). You can now see all the documents you've created through your API! You can also manually edit, add, or delete documents directly from Compass, which is fantastic for testing.


//server.js
const express = require("express");
const connectToDB = require("./src/db/db")


connectToDB()

const app = express();

const notes = [];

app.use(express.json());

app.get("/notes", (req, res) => {
  res.json(notes)
});

app.post("/notes", (req, res) => {
  const {title,content} = req.body 
  console.log(title, content);

});

app.listen(3000, () => {
  console.log("Server is running on port 3000");
});
const mongoose = require("mongoose");

function connectToDB() {
  mongoose.connect(process.env.MONGODB_URL).then(() => {
    console.log("Connected to DB");
  });
}

module.exports = connectToDB;

Environment Variables and Best Practices

Never hard-code your database credentials directly into your source code. This is a major security risk. Always use environment variables.

  • dotenv Package: This popular package loads variables from a .env file into process.env in your Node.js application.

  • .env File: Create a file named .env in your project's root directory to store sensitive information.

      MONGO_URI="your_connection_string_here"
      PORT=3000
    
  • .gitignore: Crucially, add your .env file to your .gitignore file. This prevents you from accidentally committing your secrets to a public repository like GitHub.

      # .gitignore
      node_modules
      .env
    

When to Use Atlas vs. Compass vs. Local MongoDB

Scenario

Recommended Tool

Why?

Building a production app

MongoDB Atlas

Managed, scalable, secure, and reliable.

Working on a team project

MongoDB Atlas

Provides a single, shared source of truth for the database.

Learning MongoDB offline

Local MongoDB Server

No internet required. Full control over the environment.

Visualizing/Debugging data

MongoDB Compass

Works with both Atlas and a local DB. Great for seeing what's happening.

Export to Sheets


Common Issues and Debugging

  • Connection Timeout (MongoServerSelectionError): This is almost always an IP whitelist issue. Make sure your current IP address is added to the Network Access list in Atlas.

  • Authentication Failed (MongoAuthenticationError): Double-check that the username and password in your connection string are correct. Special characters in passwords might need to be URL-encoded.

  • Model Validation Errors: If you try to save a document that doesn't match your Mongoose schema (e.g., a required field is missing), Mongoose will throw a ValidationError. Check the error message to see which field is causing the problem.


Extra Tips & Resources

  • MongoDB University: Offers free, in-depth courses on all things MongoDB.

  • Mongoose Docs: The official Mongoose documentation is your best friend for learning about schemas, queries, and advanced features.

  • Indexing: For large-scale applications, learn about database indexes. They dramatically improve query performance.

  • MERN Stack: This setup is the foundation of the MERN stack (MongoDB, Express, React, Node.js). Once your backend is ready, you can build a React frontend to consume your API.


Conclusion

Connecting MongoDB to an Express application is a core skill for any backend or full-stack developer. By using Mongoose for data modeling and MongoDB Atlas for hassle-free hosting, you can build powerful, scalable applications with ease.

0
Subscribe to my newsletter

Read articles from Code Subtle directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

Code Subtle
Code Subtle

At Code Subtle, we empower aspiring web developers through personalized mentorship and engaging learning resources. Our community bridges the gap between theory and practice, guiding students from basics to advanced concepts. We offer expert mentorship and write interactive, user-friendly articles on all aspects of web development. Join us to learn, grow, and build your future in tech!