Today I Learned About MongoDB: Setting Up And Working With It

Today I Learned About MongoDB: Setting Up And Working With It


So, I dove into MongoDB today, and honestly? It was a bit overwhelming at first. There are so many options, terms, and ways to set things up that I felt like I was drowning in choices. But after spending some quality time with it, things started clicking.

Let me share what I learned, mistakes I made, and hopefully save you some confusion along the way.

The Big Question: Which MongoDB Should I Use?

This was my first major confusion. MongoDB isn’t just one thing – it’s like going to a restaurant and being told there are three different ways to order food. Let me break it down in simple terms:

1. MongoDB Atlas (The Easy Button)

This is MongoDB in the cloud – think of it like using Gmail instead of running your own email server.

What it is: MongoDB handles all the server stuff, backups, scaling, and maintenance. You just use it.

When to use Atlas:

  • You’re building web apps and want to focus on coding, not database management
  • You’re deploying to cloud platforms (Vercel, Netlify, Heroku)
  • You’re a React/Next.js/Node.js developer who wants things to “just work”
  • You’re a beginner (seriously, start here!)

Quick example:

// Connecting from Node.js is super simple
const { MongoClient } = require('mongodb');
const uri = "mongodb+srv://username:password@cluster.mongodb.net/myDB";

const client = new MongoClient(uri);
await client.connect();
console.log("Connected to MongoDB Atlas!");

My take: This is what I chose, and I’d recommend it for 90% of developers. It’s like having a database that magically appears when you need it.

2. Enterprise Advanced (The Corporate Option)

This is for big companies who need to keep their data on their own servers.

When you’d use this:

  • Your company has strict data privacy requirements
  • You’re building apps for banks, governments, or other high-security industries
  • You have a dedicated IT team to manage databases
  • You have lots of money to spend on infrastructure

My take: Unless you’re working at a large corporation with specific requirements, skip this. It’s overkill for most projects.

3. Community Edition (The DIY Approach)

This is MongoDB running on your own computer – like cooking at home instead of ordering takeout.

When to use this:

  • You’re learning MongoDB and want to experiment
  • You’re building small personal projects
  • You need to work offline
  • You want to understand how MongoDB works under the hood

Quick setup:

# Install MongoDB locally (Ubuntu/Linux)
sudo apt install mongodb
sudo systemctl start mongodb

# Now you can connect locally
mongo

My take: Great for learning, but Atlas is usually better for real projects.

MongoDB’s Extra Features (The Cool Stuff)

Once you’ve chosen your MongoDB setup, there are some neat tools that make life easier:

MongoDB Compass (The Visual Dashboard)

Think of this as the “Instagram for databases” – it makes your data look pretty and easy to understand.

What it does:

  • Shows your data visually (no more staring at text in a terminal)
  • Lets you edit documents with a nice interface
  • Helps you build complex queries without writing code

Perfect for: Anyone who prefers clicking buttons over typing commands.

Other Useful Tools

  • Relational Migrator: Helps you move data from SQL databases (like MySQL) to MongoDB
  • Search: Built-in full-text search (like having Google inside your database)
  • Vector Search: For AI applications – store and search through embeddings for chatbots and ML projects

The MongoDB Structure: Organizations, Projects, and Clusters (Oh My!)

This part confused me the most initially. MongoDB has this hierarchy that seems unnecessarily complex at first, but it actually makes sense once you get it.

Here’s the simple version:

Organization → Project → Cluster → Database → Collection → Document

Let me explain with a real example:

Imagine you’re starting a company called “Ranjan Corp” and you’re building multiple apps. Here’s how MongoDB organizes everything:

Organization: Ranjan Corp (your MongoDB account)
├── Project: Chat App
│   └── Cluster: chat-cluster
│       └── Database: chatDB
│           ├── Collection: messages
│           ├── Collection: users
│           └── Collection: chatrooms
│
└── Project: Blog App
    └── Cluster: blog-cluster
        └── Database: blogDB
            ├── Collection: posts
            ├── Collection: comments
            └── Collection: authors

What Each Level Means:

  • Organization: Your entire MongoDB account workspace
  • Project: A folder for each app or environment (like “development” vs “production”)
  • Cluster: The actual running database server
  • Database: A container for related collections
  • Collection: Like a table in SQL – holds similar documents
  • Document: Individual records (like rows in SQL)

Setting Up MongoDB Atlas (Step by Step)

Alright, let’s get our hands dirty. Here’s exactly how I set up MongoDB Atlas:

Step 1: Create Your Account

  1. Go to https://www.mongodb.com/cloud/atlas
  2. Click “Sign Up” and create your account
  3. Verify your email (check your spam folder!)

Step 2: Create an Organization

  1. Give your organization a name (like “My Projects” or your company name)
  2. Click “Next”

Step 3: Create a Project

  1. Name your project (like “ECommerce App” or “Learning Project”)
  2. Click “Next”

Step 4: Create Your First Cluster

  1. Choose “Shared Cluster” (it’s free!)
  2. Pick a cloud provider (AWS, Google Cloud, or Azure)
  3. Choose a region close to you (I picked Mumbai since I’m in India)
  4. Name your cluster (like “my-first-cluster”)
  5. Click “Create Cluster”

Pro tip: It takes 1-3 minutes to set up – perfect time for a coffee break!

Step 5: Create a Database User

  1. Click on “Database Access” in the left sidebar
  2. Click “Add New User”
  3. Set a username and password (write these down!)
  4. Give them “Read and Write” permissions
  5. Click “Add User”

Step 6: Allow Network Access

  1. Click on “Network Access” in the left sidebar
  2. Click “Add IP Address”
  3. For development, you can click “Allow Access from Anywhere” (0.0.0.0/0)
  4. For production, add your specific IP address

Security note: “Allow Access from Anywhere” is convenient for development but not secure for production apps.

Step 7: Connect to Your Database

  1. Go back to “Clusters” and click “Connect”
  2. You’ll see three options:

Option A: Use MongoDB Compass (Visual Tool)

mongodb+srv://username:password@cluster.mongodb.net/myDatabase

Copy this connection string and paste it into Compass.

Option B: Connect from Your Node.js App

const { MongoClient } = require("mongodb");

const uri = "mongodb+srv://username:password@cluster.mongodb.net/myDatabase";
const client = new MongoClient(uri);

async function connectToDatabase() {
  try {
    await client.connect();
    console.log("Connected to MongoDB!");
    
    const db = client.db("myApp");
    const collection = db.collection("users");
    
    // Insert a test document
    await collection.insertOne({ 
      name: "John Doe", 
      email: "john@example.com",
      createdAt: new Date()
    });
    
    console.log("Document inserted!");
  } catch (error) {
    console.error("Connection failed:", error);
  }
}

connectToDatabase();

Real Project Example: Building an E-Commerce Backend

Let me show you what I actually built today – an e-commerce backend using MongoDB Atlas, Express.js, and Mongoose.

Project Structure

My E-Commerce App
├── Cluster: ecommerce-cluster
└── Database: ecommerce
    ├── Collection: users
    ├── Collection: products
    ├── Collection: orders
    └── Collection: categories

Connecting to MongoDB with Mongoose

First, I created a connection file (config/mongodb.js):

import mongoose from "mongoose";

const connectDB = async () => {
  mongoose.connection.on("connected", () => {
    console.log("✅ Database Connected Successfully!");
  });

  mongoose.connection.on("error", (err) => {
    console.error("❌ Database Connection Error:", err);
  });

  try {
    await mongoose.connect(`${process.env.MONGODB_URI}/ecommerce`);
  } catch (error) {
    console.error("Failed to connect to MongoDB:", error);
    process.exit(1);
  }
};

export default connectDB;

What’s happening here:

  • We’re connecting to our MongoDB cluster
  • The /ecommerce part specifies which database to use
  • If the database doesn’t exist, MongoDB creates it automatically
  • We’re handling connection events to know when things go right or wrong

Creating Data Models with Mongoose

Mongoose lets you define schemas (like blueprints) for your data:

User Schema

import mongoose from "mongoose";

const userSchema = new mongoose.Schema({
  name: { 
    type: String, 
    required: true 
  },
  email: { 
    type: String, 
    required: true, 
    unique: true 
  },
  password: { 
    type: String, 
    required: true 
  },
  cartData: { 
    type: Object, 
    default: {} 
  },
  role: {
    type: String,
    default: "user"
  }
}, { minimize: false });

const User = mongoose.model("User", userSchema);
export default User;

Key points:

  • unique: true prevents duplicate email addresses
  • cartData stores the user’s shopping cart as an object
  • minimize: false tells MongoDB to save empty objects instead of dropping them
  • role lets us differentiate between regular users and admins

Product Schema

const productSchema = new mongoose.Schema({
  name: { type: String, required: true },
  description: { type: String, required: true },
  price: { type: Number, required: true },
  images: [String], // Array of image URLs
  category: { type: String, required: true },
  subCategory: String,
  sizes: [String], // Array of available sizes
  colors: [String], // Array of available colors
  stock: { type: Number, default: 0 },
  bestseller: { type: Boolean, default: false },
  createdAt: { type: Date, default: Date.now }
});

const Product = mongoose.model("Product", productSchema);
export default Product;

Setting Up the Express Server

import express from "express";
import cors from "cors";
import dotenv from "dotenv";
import connectDB from "./config/mongodb.js";
import userRoutes from "./routes/userRoutes.js";
import productRoutes from "./routes/productRoutes.js";

dotenv.config();

const app = express();
const PORT = process.env.PORT || 4000;

// Connect to MongoDB
connectDB();

// Middleware
app.use(express.json());
app.use(cors());

// Routes
app.use("/api/users", userRoutes);
app.use("/api/products", productRoutes);

// Test route
app.get("/", (req, res) => {
  res.json({ message: "E-commerce API is running!" });
});

app.listen(PORT, () => {
  console.log(`🚀 Server running on http://localhost:${PORT}`);
});

User Authentication (The Secure Way)

Here’s how I implemented user registration and login:

import bcrypt from "bcryptjs";
import jwt from "jsonwebtoken";
import validator from "validator";
import User from "../models/User.js";

// Register new user
const registerUser = async (req, res) => {
  try {
    const { name, email, password } = req.body;

    // Check if user already exists
    const existingUser = await User.findOne({ email });
    if (existingUser) {
      return res.status(400).json({ 
        success: false, 
        message: "User already exists with this email" 
      });
    }

    // Validate email format
    if (!validator.isEmail(email)) {
      return res.status(400).json({ 
        success: false, 
        message: "Please enter a valid email" 
      });
    }

    // Check password strength
    if (password.length < 8) {
      return res.status(400).json({ 
        success: false, 
        message: "Password must be at least 8 characters long" 
      });
    }

    // Hash password
    const hashedPassword = await bcrypt.hash(password, 12);

    // Create new user
    const newUser = new User({
      name,
      email,
      password: hashedPassword
    });

    await newUser.save();

    // Generate JWT token
    const token = jwt.sign(
      { userId: newUser._id }, 
      process.env.JWT_SECRET,
      { expiresIn: "7d" }
    );

    res.status(201).json({
      success: true,
      message: "User created successfully",
      token,
      user: {
        id: newUser._id,
        name: newUser.name,
        email: newUser.email
      }
    });

  } catch (error) {
    console.error("Registration error:", error);
    res.status(500).json({ 
      success: false, 
      message: "Server error during registration" 
    });
  }
};

// Login user
const loginUser = async (req, res) => {
  try {
    const { email, password } = req.body;

    // Find user by email
    const user = await User.findOne({ email });
    if (!user) {
      return res.status(400).json({ 
        success: false, 
        message: "Invalid email or password" 
      });
    }

    // Check password
    const isPasswordValid = await bcrypt.compare(password, user.password);
    if (!isPasswordValid) {
      return res.status(400).json({ 
        success: false, 
        message: "Invalid email or password" 
      });
    }

    // Generate JWT token
    const token = jwt.sign(
      { userId: user._id }, 
      process.env.JWT_SECRET,
      { expiresIn: "7d" }
    );

    res.json({
      success: true,
      message: "Login successful",
      token,
      user: {
        id: user._id,
        name: user.name,
        email: user.email,
        role: user.role
      }
    });

  } catch (error) {
    console.error("Login error:", error);
    res.status(500).json({ 
      success: false, 
      message: "Server error during login" 
    });
  }
};

export { registerUser, loginUser };

Security measures implemented:

  • Passwords are hashed using bcrypt (never stored as plain text)
  • JWT tokens for authentication
  • Email validation
  • Password strength checking
  • Proper error handling without exposing sensitive info

Admin Authentication (Role-Based Access)

For admin functionality, I added role-based authentication:

const adminLogin = async (req, res) => {
  try {
    const { email, password } = req.body;

    // Find user and check if they're an admin
    const user = await User.findOne({ email });
    if (!user || user.role !== "admin") {
      return res.status(403).json({ 
        success: false, 
        message: "Access denied. Admin privileges required." 
      });
    }

    // Verify password
    const isPasswordValid = await bcrypt.compare(password, user.password);
    if (!isPasswordValid) {
      return res.status(400).json({ 
        success: false, 
        message: "Invalid credentials" 
      });
    }

    // Generate admin token
    const token = jwt.sign(
      { userId: user._id, role: user.role }, 
      process.env.JWT_SECRET,
      { expiresIn: "1d" }
    );

    res.json({
      success: true,
      message: "Admin login successful",
      token,
      user: {
        id: user._id,
        name: user.name,
        email: user.email,
        role: user.role
      }
    });

  } catch (error) {
    console.error("Admin login error:", error);
    res.status(500).json({ 
      success: false, 
      message: "Server error during admin login" 
    });
  }
};

The Mystery of Extra Databases

Here’s something that confused me initially – I created one database called ecommerce, but when I looked at my MongoDB cluster, I saw several other databases:

  • admin
  • local
  • sample_mflix
  • config

What are these?

System Databases (Don’t Touch!)

  • admin: Stores user authentication and role data
  • local: Contains replication and cluster metadata
  • config: Used for sharding configuration

Important: Never delete these! They’re essential for MongoDB to function properly.

Sample Data

  • sample_mflix: This is sample data that MongoDB provides for learning (movies, comments, etc.)

You can safely delete sample datasets if you don’t need them, but leave the system databases alone.

Key Takeaways from My MongoDB Journey

  1. Start with Atlas: It’s the easiest way to get up and running
  2. Understand the hierarchy: Organization → Project → Cluster → Database → Collection
  3. Use Mongoose for Node.js: It makes working with MongoDB much easier
  4. Security matters: Hash passwords, validate inputs, use proper authentication
  5. Don’t panic about extra databases: MongoDB creates system databases automatically
  6. Connection strings are your friend: They contain all the info needed to connect

What’s Next?

Now that I have a solid foundation, I’m planning to expand this project with:

  • Product CRUD operations
  • Shopping cart functionality
  • Order management
  • File uploads for product images
  • Admin dashboard
  • Real-time features with Socket.io

MongoDB has been surprisingly enjoyable to work with once I got past the initial confusion. The flexibility of storing JSON-like documents feels much more natural than rigid SQL tables, especially for web applications.


Thanks for reading! If you found this helpful, let me know what you’d like to see next. I’m thinking about diving into advanced MongoDB features like aggregation pipelines and indexing strategies.

— Ranjan

Leave a Comment

Your email address will not be published. Required fields are marked *