Skip to content
Share
Explore

MONGO DB Lab f24 Sept 26/27

info

Note: The Conclusion of this Lab Series:

After you complete the work in this Document: Carry on to add the Expess JS Front End with:

GiTHub Code Repository:


megaphone

We now know what

MONGO DB is, what a NOSQL database is and
how it works with JSON
how we can use JSON to do Big Data (No Primary Key operations)

Carrying on from Yesterday:

Our Learning Outcomes for today’s Class:

Front ending access to our MONGO Database with an Express JS web server using ROUTES
Creating an Express GET endpoint that performs a query (.find, .findById)
Insert a document
Update a document
Delete a document
Working with more than one collection (example: Employees and Vehicles, Books and Authors, etc)

Men's Wear E-Commerce Emporium: MongoDB Schema Design

## Project Overview

We're building a MongoDB database for a Men's Wear E-Commerce Emporium.
This platform will allow users to browse, purchase, and review men's clothing and accessories.

megaphone

Note: I have provides some of the route js files as learning starters.

Try to complete the route js files which are NOT provided here by yourself.

To compare with my solutions: See these additional lab documents:



Initial Collections
1. **Products** 2. **Categories** 3. **Customers** 4. **Orders** 5. **Reviews**
## Basic Schema Designs
### 1. Products Collection
```javascript const productSchema = new mongoose.Schema({ name: { type: String, required: true }, sku: { type: String, required: true, unique: true }, description: String, price: { type: Number, required: true }, category: { type: mongoose.Schema.Types.ObjectId, ref: 'Category' }, size: [String], color: [String], inStock: { type: Boolean, default: true }, images: [String] }, { timestamps: true });
const Product = mongoose.model('Product', productSchema); ```
### 2. Categories Collection
```javascript const categorySchema = new mongoose.Schema({ name: { type: String, required: true }, description: String, parentCategory: { type: mongoose.Schema.Types.ObjectId, ref: 'Category' } });
const Category = mongoose.model('Category', categorySchema); ```
### 3. Customers Collection
```javascript const customerSchema = new mongoose.Schema({ firstName: { type: String, required: true }, lastName: { type: String, required: true }, email: { type: String, required: true, unique: true }, password: { type: String, required: true }, address: { street: String, city: String, state: String, zipCode: String, country: String } }, { timestamps: true });
const Customer = mongoose.model('Customer', customerSchema); ```
### 4. Orders Collection
```javascript const orderSchema = new mongoose.Schema({ customer: { type: mongoose.Schema.Types.ObjectId, ref: 'Customer', required: true }, products: [{ product: { type: mongoose.Schema.Types.ObjectId, ref: 'Product' }, quantity: Number, price: Number }], totalAmount: Number, status: { type: String, enum: ['Pending', 'Shipped', 'Delivered'], default: 'Pending' }, shippingAddress: { street: String, city: String, state: String, zipCode: String, country: String } }, { timestamps: true });
const Order = mongoose.model('Order', orderSchema); ```
### 5. Reviews Collection
```javascript const reviewSchema = new mongoose.Schema({ product: { type: mongoose.Schema.Types.ObjectId, ref: 'Product', required: true }, customer: { type: mongoose.Schema.Types.ObjectId, ref: 'Customer', required: true }, rating: { type: Number, required: true, min: 1, max: 5 }, comment: String }, { timestamps: true });
const Review = mongoose.model('Review', reviewSchema); ```
Work Steps:
1. Set up a new Node.js project — 2. Install necessary dependencies (mongoose, express, nodemon, etc.) —- 3. Create a connection to your MongoDB database 4. Implement these schemas in separate files 5. Create basic CRUD operations for each collection 6. Test the database operations
This schema design provides a solid foundation for our Men's Wear E-Commerce Emporium. As we progress, we can add more complex features like inventory management, user authentication, and advanced querying.

info

Comprehensive guide for setting up the Men's Wear E-Commerce Emporium project, including all the steps you requested. This guide covers:

Setting up a new Node.js project
Installing necessary dependencies
Creating a connection to MongoDB
Implementing schemas in separate files
Creating basic CRUD operations for each collection
Instructions for testing the database operations
The guide includes detailed code snippets and step-by-step instructions for each part of the setup process. It's designed to be ready to run, allowing students to quickly set up a functional backend for the e-commerce platform.
To get started, students should follow the instructions in order, creating the necessary files and implementing the provided code.
Once everything is set up, they can start the server and use tools like Postman or curl to test the API endpoints.

The Database name in MONGO ATLAS

MONGODB_URI=mongodb+srv://username:password@cluster0.mongodb.net/mens_wear_emporium
Here, mens_wear_emporium would be your database name.

error

Complete Lab Steps for the Men's Wear E-Commerce Emporium

Work Flow Steps:

Set up a Mongo Database
Manually CRUD some records
Setup an Express JS Webserver with FORMS and use ROUTES and form data to CRUD the Mongo database.
Do Predicate Joins.

## 1. Set up a new Node.js project
1. Open your terminal and create a new directory: ```bash mkdir mens-wear-emporium cd mens-wear-emporium ```
2. Initialize a new Node.js project: —- ```bash npm init -y ```

2. Install necessary dependencies —-

Install the required packages: ```bash npm install express mongoose dotenv npm install --save-dev nodemon ```

3. Create a connection to your MongoDB database —-

1. Create a `.env` file in the root directory: ```bash touch .env ```
2. Add your MongoDB connection string to the `.env` file: —- ``` MONGODB_URI=your_mongodb_connection_string_here PORT=3000 ```
3. Create a `server.js` file in the root directory: ```bash touch server.js ```
4. Add the following code to `server.js`: ​ ```javascript const express = require('express'); const mongoose = require('mongoose'); require('dotenv').config();
const app = express(); const PORT = process.env.PORT || 3000;
// Middleware app.use(express.json());
// MongoDB Connection mongoose.connect(process.env.MONGODB_URI, { useNewUrlParser: true, useUnifiedTopology: true, }) .then(() => console.log('Connected to MongoDB')) .catch((err) => console.error('Error connecting to MongoDB:', err));
// Routes (we'll add these later)
app.listen(PORT, () => { console.log(`Server is running on port ${PORT}`); }); ``` done up to here.
## 4. Implement schemas in separate files
1. Create a `models` directory: ```bash mkdir models ```
2. Create separate files for each schema in the `models` directory: ```bash touch
models/product.js
models/category.js
models/customer.js
models/order.js
models/review.js ** ```
3. Implement each schema in its respective file:
`models/product.js`: ```javascript const mongoose = require('mongoose');
const productSchema = new mongoose.Schema({ name: { type: String, required: true }, sku: { type: String, required: true, unique: true }, description: String, price: { type: Number, required: true }, category: { type: mongoose.Schema.Types.ObjectId, ref: 'Category' }, size: [String], color: [String], inStock: { type: Boolean, default: true }, images: [String] }, { timestamps: true });
module.exports = mongoose.model('Product', productSchema); ```
`models/category.js`: ```javascript const mongoose = require('mongoose');
const categorySchema = new mongoose.Schema({ name: { type: String, required: true }, description: String, parentCategory: { type: mongoose.Schema.Types.ObjectId, ref: 'Category' } });
module.exports = mongoose.model('Category', categorySchema); ```
`models/customer.js`: ```javascript const mongoose = require('mongoose');
const customerSchema = new mongoose.Schema({ firstName: { type: String, required: true }, lastName: { type: String, required: true }, email: { type: String, required: true, unique: true }, password: { type: String, required: true }, address: { street: String, city: String, state: String, zipCode: String, country: String } }, { timestamps: true });
module.exports = mongoose.model('Customer', customerSchema); ```
`models/order.js`: ```javascript const mongoose = require('mongoose');
const orderSchema = new mongoose.Schema({ customer: { type: mongoose.Schema.Types.ObjectId, ref: 'Customer', required: true }, products: [{ product: { type: mongoose.Schema.Types.ObjectId, ref: 'Product' }, quantity: Number, price: Number }], totalAmount: Number, status: { type: String, enum: ['Pending', 'Shipped', 'Delivered'], default: 'Pending' }, shippingAddress: { street: String, city: String, state: String, zipCode: String, country: String } }, { timestamps: true });
module.exports = mongoose.model('Order', orderSchema); ```
`models/review.js`: ```javascript const mongoose = require('mongoose');
const reviewSchema = new mongoose.Schema({ product: { type: mongoose.Schema.Types.ObjectId, ref: 'Product', required: true }, customer: { type: mongoose.Schema.Types.ObjectId, ref: 'Customer', required: true }, rating: { type: Number, required: true, min: 1, max: 5 }, comment: String }, { timestamps: true });
module.exports = mongoose.model('Review', reviewSchema); ```
5. Create basic CRUD operations for each collection
1. Create a `routes` directory: ```bash mkdir routes ```
2. Create route files for each model: ```bash touch
routes/products.js
routes/categories.js
routes/customers.js
routes/orders.js
routes/reviews.js //done
3. Implement CRUD operations in each route file.
Here's an example for `routes/products.js`:
```javascript const express = require('express'); const router = express.Router(); const Product = require('../models/product');
// Create a new product router.post('/', async (req, res) => { try { const product = new Product(req.body); await product.save(); res.status(201).json(product); } catch (error) { res.status(400).json({ message: error.message }); } });
// Get all products router.get('/', async (req, res) => { try { const products = await Product.find(); res.json(products); } catch (error) { res.status(500).json({ message: error.message }); } });
// Get a single product router.get('/:id', async (req, res) => { try { const product = await Product.findById(req.params.id); if (!product) return res.status(404).json({ message: 'Product not found' }); res.json(product); } catch (error) { res.status(500).json({ message: error.message }); } });
// Update a product router.patch('/:id', async (req, res) => { try { const product = await Product.findByIdAndUpdate(req.params.id, req.body, { new: true }); if (!product) return res.status(404).json({ message: 'Product not found' }); res.json(product); } catch (error) { res.status(400).json({ message: error.message }); } });
// Delete a product router.delete('/:id', async (req, res) => { try { const product = await Product.findByIdAndDelete(req.params.id); if (!product) return res.status(404).json({ message: 'Product not found' }); res.json({ message: 'Product deleted successfully' }); } catch (error) { res.status(500).json({ message: error.message }); } });
module.exports = router; ```
4. Update `server.js` to use the routes:
```javascript const express = require('express'); const mongoose = require('mongoose'); require('dotenv').config();
const productRoutes = require('./routes/products'); const categoryRoutes = require('./routes/categories'); const customerRoutes = require('./routes/customers'); const orderRoutes = require('./routes/orders'); const reviewRoutes = require('./routes/reviews');
const app = express(); const PORT = process.env.PORT || 3000;
// Middleware app.use(express.json());
// MongoDB Connection mongoose.connect(process.env.MONGODB_URI, { useNewUrlParser: true, useUnifiedTopology: true, }) .then(() => console.log('Connected to MongoDB')) .catch((err) => console.error('Error connecting to MongoDB:', err));
// Routes app.use('/api/products', productRoutes); app.use('/api/categories', categoryRoutes); app.use('/api/customers', customerRoutes); app.use('/api/orders', orderRoutes); app.use('/api/reviews', reviewRoutes);
app.listen(PORT, () => { console.log(`Server is running on port ${PORT}`); }); ```

## 6. Test the database operations

1. Start your server: ```bash npx nodemon server.js
npx is a package runner tool that comes with npm (Node Package Manager) 5.2+ and higher. It allows you to execute npm package binaries without having to install them globally or locally. Here's a breakdown of the command:
npx: This tool is used to execute packages.
nodemon: This is a utility that monitors for any changes in your source code and automatically restarts your server.
server.js: This is the main file of your Node.js application that nodemon will run and monitor.
When you run npx nodemon server.js, here's what happens:
npx checks if nodemon is installed locally in your project's node_modules folder.
If nodemon isn't found locally, npx will temporarily download and cache the latest version of nodemon.
npx then runs nodemon server.js.
nodemon starts your Node.js application by running server.js.
nodemon continues to watch your project files. If it detects any changes in your JavaScript files, it will automatically restart your server.
The benefits of using npx nodemon instead of just node server.js are:
You don't need to globally install nodemon.
It ensures you're always using the latest version of nodemon.
Your server will automatically restart whenever you make changes to your code, which is incredibly helpful during development.
This approach is particularly useful in a classroom or learning environment because:
It simplifies the setup process for students.
It ensures all students are using the same version of nodemon.
It provides a smoother development experience with automatic server restarts.


2. Use a tool like Postman or curl to test your API endpoints. Here are some example requests:
Create a product: ``` POST http://localhost:3000/api/products Content-Type: application/json
{ "name": "Classic White Shirt", "sku": "CWS001", "description": "A timeless white shirt for any occasion", "price": 49.99, "size": ["S", "M", "L", "XL"], "color": ["White"], "inStock": true } ```
Get all products: ``` GET http://localhost:3000/api/products ```
Get a single product: ``` GET http://localhost:3000/api/products/:id ```
Update a product: ``` PATCH http://localhost:3000/api/products/:id Content-Type: application/json
{ "price": 54.99 } ```
Delete a product: ``` DELETE http://localhost:3000/api/products/:id ```
Repeat similar tests for other collections (categories, customers, orders, reviews) to ensure all CRUD operations are working correctly.
This completes the setup of your Men's Wear E-Commerce Emporium project with MongoDB, Express, and Node.js. You now have a functional backend with basic CRUD operations for all your collections.

To create data records, you would need to use the POST routes we've created.
For example, to create a product, you would send a POST request to http://localhost:3000/api/products with the product data in the request body.


The seed data script should be run as a standalone file. Here's how to set it up and run it:
Create a new file: In the root directory of your project (the same directory where your server.js file is located), create a new file called seedData.js.
Copy the code: Copy the entire code from the previous artifact into this new seedData.js file.
Run the script: To run this script, you should use Node.js directly, not through your Express server. In your terminal, make sure you're in your project's root directory.
This script will:
Connect to your MongoDB database
Clear any existing data in the collections
Create sample categories, products, customers, orders, and reviews
Log success or error messages
Disconnect from the database when done
The seed data includes:
3 categories (Shirts, Pants, Accessories)
3 products (a shirt, jeans, and a belt)
2 customers
2 orders
2 reviews
Students can modify this script to add more data or change the existing data as needed. After running this script, they'll have a populated database to work with, which will make testing their API endpoints much easier.
bash
Copy
node seedData.js
This is the seedData.js file:

const mongoose = require('mongoose'); require('dotenv').config();
// Import models const Category = require('./models/category'); const Product = require('./models/product'); const Customer = require('./models/customer'); const Order = require('./models/order'); const Review = require('./models/review');
// Connect to MongoDB mongoose.connect(process.env.MONGODB_URI, { useNewUrlParser: true, useUnifiedTopology: true, }) .then(() => console.log('Connected to MongoDB')) .catch((err) => console.error('Error connecting to MongoDB:', err));
// Seed data const seedData = async () => { try { // Clear existing data await Category.deleteMany(); await Product.deleteMany(); await Customer.deleteMany(); await Order.deleteMany(); await Review.deleteMany();
// Create categories const categories = await Category.create([ { name: 'Shirts', description: 'All types of shirts' }, { name: 'Pants', description: 'Trousers, jeans, and more' }, { name: 'Accessories', description: 'Belts, ties, and other accessories' }, ]);
// Create products const products = await Product.create([ { name: 'Classic White Shirt', sku: 'CWS001', description: 'A timeless white shirt for any occasion', price: 49.99, category: categories[0]._id, size: ['S', 'M', 'L', 'XL'], color: ['White'], inStock: true, }, { name: 'Blue Denim Jeans', sku: 'BDJ001', description: 'Comfortable and stylish blue jeans', price: 79.99, category: categories[1]._id, size: ['30', '32', '34', '36'], color: ['Blue'], inStock: true, }, { name: 'Leather Belt', sku: 'LB001', description: 'Classic brown leather belt', price: 29.99, category: categories[2]._id, size: ['One Size'], color: ['Brown'], inStock: true, }, ]);
// Create customers const customers = await Customer.create([ { firstName: 'John', lastName: 'Doe', email: 'john@example.com', password: 'password123', address: { street: '123 Main St', city: 'Anytown', state: 'CA', zipCode: '12345', country: 'USA', }, }, { firstName: 'Jane', lastName: 'Smith', email: 'jane@example.com', password: 'password456', address: { street: '456 Elm St', city: 'Otherville', state: 'NY', zipCode: '67890', country: 'USA', }, }, ]);
// Create orders const orders = await Order.create([ { customer: customers[0]._id, products: [ { product: products[0]._id, quantity: 1, price: products[0].price }, { product: products[2]._id, quantity: 1, price: products[2].price }, ], totalAmount: products[0].price + products[2].price, status: 'Pending', shippingAddress: customers[0].address, }, { customer: customers[1]._id, products: [ { product: products[1]._id, quantity: 1, price: products[1].price }, ], totalAmount: products[1].price, status: 'Shipped', shippingAddress: customers[1].address, }, ]);
// Create reviews await Review.create([ { product: products[0]._id, customer: customers[0]._id, rating: 5, comment: 'Great shirt, very comfortable!', }, { product: products[1]._id, customer: customers[1]._id, rating: 4, comment: 'Nice jeans, but a bit tight.', }, ]);
console.log('Seed data created successfully'); } catch (error) { console.error('Error creating seed data:', error); } finally { mongoose.disconnect(); } };
// Run the seed function seedData();
info

node seedData.js

This script is designed to be run independently of your main application. It will:
Connect to your database
Clear existing data
Insert the seed data
Disconnect from the database
You typically run this script once to populate your database with initial data. You wouldn't include it in your main server.js file or run it every time you start your server.
After running this script successfully, your database will be populated with the sample data, and you can then start your main application server (server.js) to interact with this data through your API endpoints.
Remember, you should have your MongoDB connection string in your .env file, as the seed script uses the same environment variable (MONGODB_URI) that your main application uses to connect to the database.
Want to print your doc?
This is not the way.
Try clicking the ··· in the right corner or using a keyboard shortcut (
CtrlP
) instead.