### 3-Tier Node.js Application with MongoDB
### Application Overview
We'll build a simple 3-tier application that manages a library of books. The application will allow users to add, view, and search for books. The three tiers are:
1. **Presentation Tier** (Front End): HTML forms served by Express for user interaction.
2. **Logic Tier** (Server): Node.js with Express handling HTTP requests.
3. **Data Tier** (Database): MongoDB storing book data.
### Workflow Instructions
1. **Set Up MongoDB**
2. **Set Up Node.js and Express**
3. **Create Mongoose Models**
4. **Create Routes and Controllers**
5. **Create Front End Forms**
6. **Run the Application**
### Step-by-Step Guide
#### Step 1: Set Up MongoDB
Ensure you have MongoDB installed and running. If using MongoDB Atlas, create a cluster and get the connection string.
#### Step 2: Set Up Node.js and Express
1. **Create Project Directory**
```bash
mkdir libraryApp
cd libraryApp
```
2. **Initialize Project**
```bash
npm init -y
```
3. **Install Dependencies**
```bash
npm install express mongoose ejs body-parser
```
4. **Create Project Structure**
```bash
mkdir models views routes controllers
touch app.js
```
#### Step 3: Create Mongoose Models
Create `models/book.js`:
```javascript
const mongoose = require('mongoose');
const bookSchema = new mongoose.Schema({
title: String,
author: String,
genre: String,
publishedYear: Number
});
module.exports = mongoose.model('Book', bookSchema);
```
#### Step 4: Create Routes and Controllers
Create `routes/index.js`:
```javascript
const express = require('express');
const router = express.Router();
const bookController = require('../controllers/bookController');
router.get('/', bookController.index);
router.get('/books', bookController.getBooks);
router.get('/book/new', bookController.newBookForm);
router.post('/book', bookController.createBook);
module.exports = router;
```
Create `controllers/bookController.js`:
```javascript
const Book = require('../models/book');
exports.index = (req, res) => {
res.redirect('/books');
};
exports.getBooks = async (req, res) => {
const books = await Book.find();
res.render('books', { books });
};
exports.newBookForm = (req, res) => {
res.render('newBook');
};
exports.createBook = async (req, res) => {
const { title, author, genre, publishedYear } = req.body;
const book = new Book({ title, author, genre, publishedYear });
await book.save();
res.redirect('/books');
};
```
#### Step 5: Create Front End Forms
Create `views/layout.ejs`:
```html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Library App</title>
</head>
<body>
<header>
<h1>Library App</h1>
<nav>
<a href="/">Home</a>
<a href="/books">Books</a>
<a href="/book/new">Add Book</a>
</nav>
</header>
<main>
<%- body %>
</main>
</body>
</html>
```
Create `views/books.ejs`:
```html
<% include layout %>
<h2>Books</h2>
<ul>
<% books.forEach(book => { %>
<li><%= book.title %> by <%= book.author %> (<%= book.publishedYear %>) - <%= book.genre %></li>
<% }) %>
</ul>
```
Create `views/newBook.ejs`:
```html
<% include layout %>
<h2>Add New Book</h2>
<form action="/book" method="POST">
<label for="title">Title:</label>
<input type="text" id="title" name="title" required><br>
<label for="author">Author:</label>
<input type="text" id="author" name="author" required><br>
<label for="genre">Genre:</label>
<input type="text" id="genre" name="genre" required><br>
<label for="publishedYear">Published Year:</label>
<input type="number" id="publishedYear" name="publishedYear" required><br>
<button type="submit">Add Book</button>
</form>
```
#### Step 6: Set Up the Main Application File
Create `app.js`:
```javascript
const express = require('express');
const mongoose = require('mongoose');
const bodyParser = require('body-parser');
const app = express();
// MongoDB Local URI
const uri = "mongodb://localhost:27017/library";
// Connect to MongoDB
mongoose.connect(uri, { useNewUrlParser: true, useUnifiedTopology: true })
.then(() => console.log('Connected to MongoDB'))
.catch(err => console.error('Could not connect to MongoDB...', err));
// Middleware
app.use(bodyParser.urlencoded({ extended: true }));
app.set('view engine', 'ejs');
// Routes
const indexRoutes = require('./routes/index');
app.use('/', indexRoutes);
// Start the Server
const port = process.env.PORT || 3000;
app.listen(port, () => {
console.log(`Server is running on port ${port}`);
});
```
### Running the Application
1. **Start MongoDB Server** (if not already running):
```bash
mongod
```
2. **Start the Application**:
```bash
node app.js
```
3. **Open Browser**:
- Go to `http://localhost:3000/`
- You should see the home page of the Library App.
4. **Add New Book**:
- Navigate to `http://localhost:3000/book/new`
- Fill out the form and submit to add a new book.
5. **View Books**:
- Navigate to `http://localhost:3000/books` to see the list of books.
### Conclusion
This guide walks you through the process of setting up a 3-tier Node.js application with a MongoDB backend. It includes setting up the database, creating models, defining routes and controllers, and building the front end with forms. By following these steps, students will gain practical experience in building a full-stack application.