DEV Community

Swislok-Dev
Swislok-Dev

Posted on

MongoDB and Express CRUD

Backend Setup

Create files in the respective directories all under a backend folder.

config/db.js
controllers/goalController.js
middleware/errorMiddleware.js
models/goalModel.js
routes/goalRoutes.js
server.js

In the root directory have a .env file for db key and other environment variables.

.env

NODE_ENV = development
PORT = 5001
MONGO_URI = <connection to mongoDB uri>
Enter fullscreen mode Exit fullscreen mode

Server.js

Initial config of starting routes for backend.

const express = require("express");
const colors = require("colors");
const dotenv = require("dotenv").config();
const connectDb = require('./config/db')
const port = process.env.PORT || 5001;
const { errorHandler } = require("./middleware/errorMiddleware");

connectDb()

const app = express();

app.use(express.json());
app.use(express.urlencoded({ extended: false }));

app.use("/api/goals", require("./routes/goalRoutes"));

app.use(errorHandler);

app.listen(port, () => console.log(`Server start on port ${port}`));
Enter fullscreen mode Exit fullscreen mode

Backend files

./config/db.js

const mongoose = require('mongoose');

const connectDB = async () => {
  try {
    const conn = await mongoose.connect(process.env.MONGO_URI);
    console.log(
      `MongoDB Connected: ${conn.connection.host}`.cyan.underline
    );
  } catch (error) {
    console.log("error", error);
    process.exit(1);
  }
};

module.exports = connectDB;
Enter fullscreen mode Exit fullscreen mode

./controllers/goalController.js

const asyncHandler = require('express-async-handler');

const Goal = require('../models/goalModel');

const getGoals = asyncHandler(async (req, res) => {
  const goals = await Goal.find();
  res.status(200).json(goals);
});

const setGoal = asyncHandler(async (req, res) => {
  if (!req.body.text) {
    res.status(400);
    throw new Error("Please add a text field");
  }

  const goal = await Goal.create({
    text: req.body.text,
  });

  res.status(200).json(goal);
});
// Other CRUD actions below

module.exports = {
  getGoals,
  setGoal,
  ...
}; 
Enter fullscreen mode Exit fullscreen mode

./middleware/errorMiddleware.js

const errorHandler = (err, req, res, next) => {
  const statusCode = res.statusCode ? res.statusCode : 500;
  res.status(statusCode);

  res.json({
    message: err.message,
    stack: process.env.NODE_ENV === "production" ? null : err.stack,
  });
};

module.exports = {
  errorHandler,
};

// "./models/goalModel.js"
const mongoose = require("mongoose");

const goalSchema = mongoose.Schema(
  {
    text: {
      type: String,
      required: [true, "Please add a text value"],
    },
  },
  {
    timestamps: true,
  }
);

module.exports = mongoose.model("Goal", goalSchema);
Enter fullscreen mode Exit fullscreen mode

./routes/goalRoutes.js

const express = require("express");
const router = express.Router();
const {
    getGoals,
    setGoal,
    updateGoal,
    deleteGoal,
} = require("../controllers/goalController");

router.get('/', (req, res) => {
  res.status(200).json({ message: "Get goals" });
});

router.post('/', (req, res) => {
  res.status(200).json({ message: "Set goal" });
});

router.put('/:id', (req, res) => {
  res.status(200).json({ message: `Update goal ${req.params.id}` });
});

router.delete('/:id', (req, res) => {
  res.status(200).json({ message: `Delete goal ${req.params.id}` });
});

module.exports = router;
Enter fullscreen mode Exit fullscreen mode

Refactor the router methods to clean it up.

// "./routes/goalRoutes.js"
...

router.route('/').get(getGoals).post(setGoal)
router.route('/:id').delete(deleteGoal).put(updateGoal)

...

Enter fullscreen mode Exit fullscreen mode

Generic setup for routes and error handling get things setup for quick. Check with a REST client to verify all routes are working with proper response.

All of the controller actions are asynchronous and will require the use of async/await

Making use of express.js is still relatively new to me coming from a Rails background, but the use of JavaScript and the refactoring involved to keep separation of concerns in order is more or less straight forward.

Discussion (0)