Application with MongoDB and User CRUD Operations


Creating a social media website in Node.js and MongoDB is a substantial project, and it would be beyond the scope of a single response to cover all the details. However, I can provide you with a high-level overview and the steps you need to follow to get started. You'll need to have some experience with Node.js, MongoDB, and web development to tackle this project.


Example

middleware/middleware.js

The provided code appears to be a Node.js middleware function designed to validate and process data from HTTP requests, particularly for a REST API.

const moment = require("moment");
const ObjectId = require("mongoose").Types.ObjectId;

String.prototype.isEmail = function () {
  return !!this.match(/^\w+@[a-zA-Z_]+?\.[a-zA-Z]{2,3}$/);
};

exports.isValidData = (req, res, next) => {
  const dateString = req.body.dob;
  const dateFormat = "YYYY-MM-DD";

  if (req.method == "POST" || req.method == "PUT") {
    if (req.body.name == undefined || req.body.name == "") {
      res.status(400).json({ error: "Name cannot be empty" });
      return;
    }

    if (!moment(dateString, dateFormat, true).isValid()) {
      res.status(400).json({ error: "Invalid Date Format required(YYYY-MM-DD)" });
      return;
    }
    if (isNaN(req.body.age)) {
      res.status(400).json({ error: "Invalid Age Format Must be Number" }); //Bad Request
      return;
    }

    if (!req.body.email.isEmail()) {
      res.status(400).json({ error: "Invalid Email Address" });
      return;
    }
  }

  const allowedMethods = ["GET", "PUT", "DELETE"];

  if (allowedMethods.includes(req.method)) {
    if (!ObjectId.isValid(req.params.id)) {
      res.status(400).json({ error: "Invalid User Id" });
      return;
    }
  }
  return next();
};
  1. It defines a custom method isEmail for JavaScript String objects, which is used to validate if a string conforms to a basic email format.
  2. It exports a middleware function isValidData, which is meant to be used in an Express.js or similar application. This middleware performs data validation based on the HTTP request method (POST, PUT, GET, DELETE) and certain conditions.
  3. For POST and PUT requests, it checks if the request body contains valid data for fields like 'name' (non-empty), 'dob' (date in the format YYYY-MM-DD), 'age' (a number), and 'email' (valid email format).
  4. For GET, PUT, and DELETE requests, it checks if the id parameter in the URL is a valid MongoDB ObjectId. This check is useful for routes that involve database operations on user entities.
  5. If any validation check fails, it responds with a 400 (Bad Request) status and an error message. If all checks pass, it calls the next middleware or route handler in the chain.

modal/userModel.js

The provided code defines a Mongoose model for a "User" schema in a MongoDB database.

This line imports the Mongoose library, which is a popular Object Data Modeling (ODM) library for MongoDB, used to define data models and interact with a MongoDB database.

const mongoose = require("mongoose");
  • module.exports is used to make this model accessible to other parts of your Node.js application. It exports the Mongoose model.
  • mongoose.model is a method provided by Mongoose for defining and creating a model.
  • "User" is the name you're giving to this model. It will be used to interact with the "users" collection in your MongoDB database. In MongoDB, collections are similar to tables in relational databases, and each document in a collection corresponds to a record.
  • The second argument is an object that defines the schema for the "User" model. In this case, it specifies the structure of a user document, including the data types of its fields.
    • name: { type: String } defines a field called "name" with a data type of String.
    • email: { type: String } defines a field called "email" with a data type of String.
    • dob: { type: Date } defines a field called "dob" with a data type of Date, indicating it should store date values.
    • age: { type: Number } defines a field called "age" with a data type of Number.
    • city: { type: String } defines a field called "city" with a data type of String.

This schema definition establishes the structure and data types of the documents that will be stored in the "users" collection in your MongoDB database. It essentially defines what a "User" document should look like.

module.exports = mongoose.model(
  "User",
  {
    name: { type: String },
    email: { type: String },
    dob: { type: Date },
    age: { type: Number },
    city: { type: String },
  },
  "users"
);

In summary, this code creates a Mongoose model for a "User" schema with specified fields and data types. It allows you to interact with the "users" collection in your MongoDB database using this model, making it easier to perform CRUD (Create, Read, Update, Delete) operations on user data.

routes/userRoutes.js

The provided code is an example of an Express.js router that defines various routes and handlers for a RESTful API to perform CRUD (Create, Read, Update, Delete) operations on a "User" model. This code assumes that you have a "User" model defined, possibly as shown in your previous question.

const express = require("express");
const router = express.Router();
const User = require("../model/userModel");
const { isValidData } = require("../middleware/middleware");
  • express is the Express.js framework that simplifies the creation of web applications and APIs in Node.js.
  • router is an instance of the Express Router, which is used to define routes and route handlers.
  • User is the Mongoose model for the "User" schema. It allows interaction with the MongoDB collection associated with users.
  • { isValidData } imports the isValidData middleware function from another module.
// Get all Records
router.get("/", (req, res) => {
  User.find()
    .then((data) => res.send(data))
    .catch((err) => console.log(err));
});

This route handles HTTP GET requests to the root path ("/"). It uses the Mongoose find() method to retrieve all user records from the MongoDB collection, and then it sends the retrieved data as a response. If an error occurs, it logs the error.

// Read a Single Record
router.get("/:id", isValidData, (req, res) => {
  User.findById(req.params.id)
    .then((data) => {
      if (data) {
        res.send(data);
      } else {
        res.status(404).json({
          error: `No User Record Found in _id ${req.params.id}`,
        });
      }
    })
    .catch((err) => console.log(err));
});

This route handles HTTP GET requests with a user ID as a parameter. It uses the isValidData middleware to validate the user ID. If the ID is valid, it uses User.findById() to find a single user record by ID. If a user with that ID exists, it sends the user data as a response. If no user is found, it returns a 404 status code with an error message.

// Create New Record
router.post("/", isValidData, (req, res) => {
  User.create(req.body)
    .then((data) => res.status(201).json(data))
    .catch((err) => console.log(err));
});

This route handles HTTP POST requests to create a new user record. It uses the isValidData middleware to validate the request body. If the data is valid, it uses User.create() to create a new user based on the data in the request body. If the user is created successfully, it sends a 201 status code (indicating "Created") and the created user data as a response.

// Update a Record
router.put("/:id", isValidData, (req, res) => {
  User.findByIdAndUpdate(req.params.id, req.body, { new: true })
    .then((data) => res.status(201).json(data))
    .catch((err) => console.log(err));
});

This route handles HTTP PUT requests to update an existing user record. It uses the isValidData middleware to validate the user ID and request body. If the data is valid, it uses User.findByIdAndUpdate() to find and update a user record by ID. The { new: true } option ensures that the updated user data is returned. It sends a 201 status code with the updated user data as a response.

// Delete a Record
router.delete("/:id", (req, res) => {
  User.findByIdAndDelete(req.params.id)
    .then(() => res.status(201).json({ msg: "User Details Deleted Success" }))
    .catch((err) => console.log(err));
});

This route handles HTTP DELETE requests to delete a user record by ID. It uses User.findByIdAndDelete() to find and remove the user record. It sends a 201 status code with a success message as a response after the deletion is complete.

Finally, the router is exported, making these routes and handlers available for use in the main application file (e.g., app.js) to define the API endpoints for user management.

index.js

This code is a Node.js application using the Express.js framework to create a web server for an API and serve web content. It also connects to a database using Mongoose.

Import Required Modules:

  • express is used to create an Express.js application, which simplifies building web servers and APIs in Node.js.
  • body-parser is a middleware used to parse incoming request bodies in JSON format.
const express = require("express");
const bodyParser = require("body-parser");

Create an Express Application:

const app = express();
const port = "3000";
  • app is an instance of the Express application, which will be used to define routes and handle HTTP requests.
  • port specifies the port number on which the server will listen for incoming requests. In this case, it's set to 3000.

Use Body Parser Middleware:

app.use(bodyParser.json());

This line sets up the body-parser middleware to parse JSON data in incoming requests. It allows the application to work with JSON data in request bodies.

Import Local Modules:

//Local Imports
const connectDb = require("./db");

This line imports a local module named connectDb, which is expected to handle the database connection.

Define Routes and Middleware:

//Routes
const userRoutes = require("./routes/userRoutes");
app.use("/api/users", userRoutes);

This code imports a set of routes from a local module named userRoutes and associates them with the "/api/users" path. Any request starting with "/api/users" will be handled by the routes defined in the userRoutes module. This is a common practice for structuring and organizing your API.

Define a Route for the Home Page:

//Home Page
app.get(["/", "/home", "/index"], (req, res) => {
  res.send("Welcome to Tutor Joes Online Web Development Course");
});

This code defines a route for the home page that responds to GET requests at the root path ("/"), "/home," or "/index." When accessed, it sends a simple welcome message as a response.

Connect to the Database and Start the Server:

//Database Connection Check
connectDb()
  .then(() => {
    console.log("Database Connected Success");
    //Start Server
    app.listen(port, () => {
      console.log(`Server is running on port ${port}`);
    });
  })
  .catch((err) => console.log(err));
  • This code first calls the connectDb function to establish a connection to the database. The connection is asynchronous and returns a Promise.
  • If the database connection is successful, it logs a "Database Connected Success" message.
  • Then, it starts the Express server on the specified port (in this case, port 3000) and logs a message to indicate that the server is running.

Overall, this code sets up an Express.js application with routes, middleware for parsing JSON data, and a database connection. It listens for incoming requests on the specified port and handles them based on the defined routes and middleware. It provides a simple home page route as well.

db.js

const mongoose = require("mongoose");

const uri = "mongodb://127.0.0.1:27017/usercrud";
module.exports = () => {
  return mongoose.connect(uri);
};
  • Imports the Mongoose library, which provides an elegant and flexible way to work with MongoDB data in a Node.js application.
  • uri is a string that represents the Uniform Resource Identifier (URI) for the MongoDB database. It specifies the connection details, including the hostname (127.0.0.1), port (27017), and the database name ("usercrud"). You can replace this URI with the actual connection details for your MongoDB database.
  • This module exports a function without a name, which can be referred to as an anonymous function. This function is intended to be called to establish a connection to the MongoDB database specified by the uri variable.
  • Inside the function, mongoose.connect(uri) is called. This method connects to the MongoDB database using the provided URI. The mongoose.connect method returns a Promise, which resolves when the connection is established or rejects if there is an error during the connection process.
  • When this function is invoked in your application, it initiates the connection to the MongoDB database specified in the uri.

package.json

{
  "name": "004_api",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "start": "node index",
    "dev": "nodemon index"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "devDependencies": {
    "nodemon": "^3.0.1"
  },
  "dependencies": {
    "body-parser": "^1.20.2",
    "express": "^4.18.2",
    "moment": "^2.29.4",
    "mongoose": "^7.6.3"
  }
}

In summary, this program demonstrates the use of class inheritance, where the <mark> Student and Staff</mark> classes inherit common attributes and methods from the <mark> Details</mark> class. It showcases how you can collect and display specific information for different types of objects (students and staff) while reusing and customizing common functionality provided by the parent class.