9 Topics
Chapter•45 Minutes

MongoDB Atlas and Mongoose Integration

Create a MongoDB database, configure database access, connect using Mongoose, define schemas, and understand MongoDB document modeling.

Understand MongoDB and Mongoose

MongoDB is a document-oriented NoSQL database.

Instead of storing information in traditional relational tables, MongoDB stores documents inside collections.

A MongoDB document resembles a JSON object, but MongoDB internally stores documents using BSON.

For example, a users collection might contain:

{
  "_id": "ObjectId(...) ",
  "name": "John Doe",
  "email": "john@example.com",
  "age": 25,
  "isActive": true
}

Mongoose is an Object Data Modeling library that provides a structured way to interact with MongoDB from Node.js.

Mongoose provides:

  • Schema definitions.
  • Models.
  • Validation.
  • Middleware hooks.
  • Query helpers.
  • Population.
  • Transactions support through MongoDB sessions.

We will use Mongoose to define and manage our user collection.

MongoDB vs Mongoose

FeatureMongoDBMongoose
TypeDatabaseODM library
StorageBSON documentsNo direct storage
SchemaFlexible document structureApplication-level schemas
ValidationDatabase validation optionsSchema-level validation
ExecutionDatabase serverNode.js application
Key Takeaways
  • MongoDB stores documents in collections.

  • Mongoose provides an application-level modeling layer.

  • Mongoose schemas help enforce consistent document structures.

Create a MongoDB Atlas Account

MongoDB Atlas provides a managed MongoDB database service.

Follow these steps:

  1. Open MongoDB Atlas.
  2. Create an account or sign in.
  3. Create a project.
  4. Create a database deployment.
  5. Select an available free deployment option if suitable for your learning project.
  6. Choose a cloud provider and region.
  7. Create the deployment.
  8. Wait for the database deployment to become available.

The exact free-tier availability and deployment options may vary by region and current Atlas plans.

After creating the deployment, configure database access and network access before connecting from Node.js.

Local MongoDB Alternative

You can also use a locally installed MongoDB Community Server. The application code remains the same; only MONGODB_URI changes.

Key Takeaways
  • MongoDB Atlas provides managed database hosting.

  • Create a project and database deployment.

  • Configure database access before connecting.

Configure Database Access

MongoDB Atlas requires a database user to authenticate database connections.

Follow these steps:

  1. Open the Database Access section.
  2. Add a new database user.
  3. Choose password-based authentication.
  4. Generate a strong password.
  5. Assign the minimum database privileges required for the application.
  6. Save the database user.

Do not confuse your MongoDB Atlas website login with the database user credentials.

The application uses the database user credentials to authenticate its MongoDB connection.

For production applications, follow the principle of least privilege and avoid using broad administrative roles.

Database Credentials

Do not share database credentials or include them in frontend JavaScript. Only the backend should connect using privileged database credentials.

Key Takeaways
  • Atlas database users are different from Atlas website users.

  • Use strong database passwords.

  • Grant only the database permissions required by the application.

Configure MongoDB Network Access

MongoDB Atlas also restricts which IP addresses can access your database deployment.

Open Network Access in Atlas.

Add the public IP address of your development machine.

For local development, use the current public IP address rather than allowing every IP address.

Allowing 0.0.0.0/0 makes the database reachable from all IPv4 addresses, subject to authentication and other controls. It is not a recommended production configuration.

For production, use private networking or carefully controlled network access wherever possible.

Avoid Unrestricted Network Access

Do not use unrestricted IP access for production databases. Restrict access to trusted networks and application infrastructure.

Key Takeaways
  • Atlas uses network access rules.

  • Allow your development IP address.

  • Restrict production database connectivity.

Get the MongoDB Connection String

Open your Atlas database deployment and select Connect.

Choose the Drivers connection option.

Select Node.js and copy the connection string.

It generally looks like this:

mongodb+srv://<username>:<password>@cluster.example.mongodb.net/<database>

Replace the placeholders with your database username, password, and database name.

Special characters in database credentials must be percent-encoded when embedded in a MongoDB URI.

Add the resulting connection string to the MONGODB_URI environment variable.

Never expose this connection string to the browser.

.env
MONGODB_URI=mongodb+srv://dbuser:encoded-password@cluster.example.mongodb.net/rest_api_db

Stores the MongoDB connection string in a backend environment variable. Replace the example hostname and credentials with your actual Atlas connection details.

Key Takeaways
  • Copy the connection string from the Atlas Drivers section.

  • Use the database username and password.

  • Encode special characters in credentials.

  • Keep the connection string on the backend.

Connect Node.js to MongoDB

Create src/config/database.js.

Import Mongoose and define a reusable connection function.

The application should wait for the database connection before accepting requests that depend on MongoDB.

Mongoose provides mongoose.connect() for establishing the connection.

src/config/database.js
import mongoose from 'mongoose';

export async function connectDatabase() {
  const connectionString = process.env.MONGODB_URI;

  if (!connectionString) {
    throw new Error('MONGODB_URI is not configured');
  }

  await mongoose.connect(connectionString, {
    serverSelectionTimeoutMS: 10000
  });

  console.log(`MongoDB connected: ${mongoose.connection.name}`);
}

export async function disconnectDatabase() {
  await mongoose.disconnect();
}

Creates reusable database connection and disconnection functions. The server selection timeout limits how long Mongoose waits to find a suitable MongoDB server.

Key Takeaways
  • mongoose.connect() establishes the MongoDB connection.

  • Check required environment variables before connecting.

  • Separate database lifecycle management from HTTP server initialization.

Verify the MongoDB Connection

Before creating models, verify that the backend can connect to MongoDB.

You can temporarily create a small test script or integrate the connection function into your server startup.

When the connection succeeds, you should see a message similar to:

MongoDB connected: rest_api_db

If the connection fails, check:

  1. Whether the MongoDB deployment is running.
  2. Whether the connection string is correct.
  3. Whether the database username is correct.
  4. Whether the password is correctly encoded.
  5. Whether your IP address is allowed.
  6. Whether your network permits outbound database connections.

Do not proceed with database-dependent endpoints until the connection works.

Database Debugging

Mongoose connection failures commonly result from incorrect credentials, network restrictions, or invalid connection strings.

Key Takeaways
  • Verify database connectivity before implementing CRUD.

  • Check credentials and network access when connection fails.

  • Use the database connection name to confirm the selected database.

Create the User Mongoose Model

Create src/models/user.model.js.

A Mongoose schema defines the structure and behavior of documents stored in a collection.

For our application, a user will contain:

  • name
  • email
  • password
  • age
  • role
  • isActive
  • createdAt
  • updatedAt

The email should be unique, and the password should be excluded from ordinary query results by default.

Mongoose timestamps automatically manage createdAt and updatedAt.

Unique Is an Index, Not a Validator

The unique option creates a unique index. Duplicate email registration can produce a MongoDB duplicate-key error. Handle that error explicitly in your service or centralized error handler.

src/models/user.model.js
import mongoose from 'mongoose';

const userSchema = new mongoose.Schema({
  name: {
    type: String,
    required: true,
    trim: true,
    minlength: 2,
    maxlength: 80
  },
  email: {
    type: String,
    required: true,
    unique: true,
    lowercase: true,
    trim: true
  },
  password: {
    type: String,
    required: true,
    select: false
  },
  age: {
    type: Number,
    min: 18,
    max: 120
  },
  role: {
    type: String,
    enum: ['user', 'admin'],
    default: 'user'
  },
  isActive: {
    type: Boolean,
    default: true
  }
}, {
  timestamps: true
});

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

Defines the user schema with field types, constraints, defaults, a unique email index declaration, and automatic timestamps.

Key Takeaways
  • Mongoose schemas define document structures.

  • Schema options support validation and default values.

  • The timestamps option manages createdAt and updatedAt.

  • The unique option creates a database index.

Understand Mongoose Models and Documents

A Mongoose model is created from a schema and provides an interface for interacting with a MongoDB collection.

For example:

const user = await User.findOne({ email: 'john@example.com' });

Here:

  • User is the Mongoose model.
  • findOne() is a model query method.
  • The result is a Mongoose document or null.

A Mongoose document represents an individual database record and provides methods such as save() and toObject().

Models are also used for creating, updating, and deleting documents.

Create a User Document
const user = new User({
  name: 'John Doe',
  email: 'john@example.com',
  password: 'hashed-password'
});

await user.save();

console.log(user._id);

Creates a Mongoose document and persists it to MongoDB using save(). The password value is illustrative; real registration must hash passwords before saving.

Key Takeaways
  • Models provide database operations.

  • Documents represent individual records.

  • save() persists a new or modified document.