← Back to all tutorials

Saving Data to MongoDB

Connect to MongoDB with Mongoose and save documents from POST requests — your first real data persistence.

Saving Data to MongoDB

With a schema and model defined, it is time to connect to MongoDB and save real data. In this episode you will set up the database connection and update your POST route to create and persist documents.

Setting Up MongoDB

You can use MongoDB Atlas (free cloud-hosted) or install MongoDB locally. Atlas is recommended because it requires no local installation.

Connecting to MongoDB

// index.js
const mongoose = require('mongoose');

const dbURI = 'mongodb+srv://user:pass@cluster.mongodb.net/ninjago?retryWrites=true';

mongoose.connect(dbURI)
    .then(() => {
        console.log('Connected to MongoDB');
        app.listen(PORT, () => {
            console.log(`Server running on port ${PORT}`);
        });
    })
    .catch(err => {
        console.error('MongoDB connection error:', err);
    });

The server starts only after the database connection is established. If the connection fails, the error is caught and logged. This ensures your API does not accept requests without a working database.

Saving a Document (POST)

// routes/ninjas.js
const Ninja = require('../models/ninja');

router.post('/', async (req, res) => {
    try {
        const ninja = new Ninja(req.body);
        const savedNinja = await ninja.save();
        res.status(201).json(savedNinja);
    } catch (err) {
        res.status(400).json({ error: err.message });
    }
});

Step by Step

StepCodeWhat Happens
1new Ninja(req.body)Creates a new Ninja instance from the request data
2ninja.save()Validates the data and saves it to MongoDB
3res.status(201).json()Sends back the saved document (including the generated _id)
catchres.status(400)If validation fails, sends a 400 error with the message

Testing with Postman

POST http://localhost:3000/api/ninjas

Body:
{
    "name": "Ryu",
    "rank": 5,
    "available": true
}

Response: 201 Created
{
    "_id": "65a1b2c3d4e5f6a7b8c9d0e1",
    "name": "Ryu",
    "rank": 5,
    "available": true,
    "createdAt": "2024-01-15T10:30:00.000Z",
    "updatedAt": "2024-01-15T10:30:00.000Z"
}

The response includes the auto-generated _id, the data you sent, and the createdAt/updatedAt timestamps from the schema.

Validation in Action

POST http://localhost:3000/api/ninjas
Body: { "rank": 5 }   ← missing required "name"

Response: 400 Bad Request
{ "error": "Ninja validation failed: name: Name is required" }

Mongoose automatically validates data against the schema before saving. If validation fails, the .save() method throws an error with a descriptive message.

Using Environment Variables

npm install dotenv
// .env
MONGODB_URI=mongodb+srv://user:pass@cluster.mongodb.net/ninjago

// index.js
require('dotenv').config();
mongoose.connect(process.env.MONGODB_URI);

Never hardcode database credentials in your source code. Use environment variables via dotenv and add .env to .gitignore.

Key Takeaways

  • mongoose.connect() establishes the database connection — start your server only after it succeeds
  • new Model(data) creates a document instance; .save() validates and persists it
  • Mongoose validates data against the schema automatically and throws descriptive errors
  • Use environment variables for database credentials — never hardcode them