Express + Mongo Simplified
Published: 2021-09-02 23:48:34

*More notes I was taking in class to capture the steps to use Mongo DB and express routes... WIP*

**File List: **
[package.json](#)
[.env](#)
[config.js](#)
[index.js](#)
[routes.js](#)
[controller.js](#)

Getting started, we are using the zoo database.

*Because we have everything installed, Mongo is always running in the background*

## package.json
Will need to add the following: 
*express
*mongodb
*dotenv

## .env
Copy string from mongosh and add to this file.
Also add the port number here.

## config.js
Use this file to connect the env with the rest of the application, export 
```
import dot env from 'dotenv';
dotenv.config();
export default {
port: process.env.PORT || 3000,
db: proces.env.DB_CLIENT_URL
};
```
If the port number is not provided in env file, it will default to 3000 (aka short circuit pattern).

Next, import config into index.js

## loader.js
Use this to set up the mongo client & export it out. 

```
import { MongoClient } from "mongodb";
import config from "./config.js";

const client = new MongoClient(config.db);

client
  .connect()
  .then(() => {
    console.info("Connected to MongoDB");
  })
  .catch((err) => {
    console.error("Error starting MongoDB Client");
    process.exit(1);
    // using "1" as exit code because it's not a graceful exit
    // using "0" as exit code because it's a graceful exit
  });

process.on("SIGINT", () => {
  client.close().then(() => {
    console.info("MongoDB connection closed");
    process.exit(0);
  });
});

export default client;
```

## index.js
*import
*declare
*get path, call back
*listen
... everything between localhost:3000/ and localhost:3000/api

## routes.js
*import 
*declare
*get path, call back
*use

## controller.js
Creating a method that connects to the database collection we want to use... then import it into routes.js
```
const controller = {
async index()
 {
const animals = await client.db("zoo")
.collection("animals")
.find()
.toArray();
return animals;
}}
```
.find creates a cursor that allows us to go into the array and do stuff like filter or sort. 
We can pass in a parameter into the index() that will allow us to use the fields in the routes... will need to interpolate using a bracket when calling it. 

## routes.js
*create a route that gets all the animals*
http://localhost:3000/animals
```
import animalsController from "./controller.js"
router.get("/animals", async (_, res)=>{
const animals = await animalsController.index();
res.json(animals);
}
```

*Create a route that sorts by a field*
http://localhost:3000/animals?sort=class
In the route we will add the parameters into the path and then we'll need to interpolate that parameter in the controller.
```
const controller = {
async index(sortBy)
 {
const animals = await client.db("zoo")
.collection("animals")
.find()
.sort({ name: 1 })
.toArray();
return animals;
}}
```

And then we'll need to update the router to include the sort parameter
```
import animalsController from "./controller.js"
router.get("/animals", async (req, res)=>{
const animals = await animalsController.index(req.query.sort);
res.json(animals);
}
```

## CRUD Routes
**FROM HERE WE STARTED USING A NEW DATABASE FOR A NOTE TAKER APP**
Mongo DB is going to create a new collection dynamically. Won't need to set anything up beforehand since we already have everything connected in the .env.

First, need to add json middleware to index.js
```
import morgan from "morgan"
app.use(morgan("dev"))
app.use(express.json());
```
*Morgan logs the routes in node*

Mount the routes
```
import apiRouter from "./router.js"
app.use("/api", apiRouter)
```

### POST
*Starting the post route to create a new note*
http://localhost:3000/api/

```
router.post("/", (req, res)=>{
res.json(req.body);
});
```

Practicing iterative coding...
Go back to the controller.
```
import client from "./loader.js";
export default {
 create(newNote) {
return client.db("noteTaker").collection("notes").insertOne(newNote);
}
}
```

Then add controller to routes file.
```
import noteController from "./controller.js"
router.post("/", (req, res)=>{
const newNote = await noteController.create(req.body);
res.json(req.body);
});
```

Add in try/catch for errors in the route
```
router.post("/notes", async (req, res)=>{
try {
const newNote = await noteController.create(req.body);
res.json(req.body);
} catch (error) {
rest.status(400).json(error.message)
}
});
```

### GET
Prints all the notes in the database.

Starting with the routes:
```
router.get("/notes", async (req, res) => {
try {
const notes = await noteController.index();
res.json(notes)
} catch (error) {
res.state(400).json(error.message)}
}
```

then add to the controller...
This file is using the mongo db library of methods.
**Link to those methods**
```
import client from "./loader.js";
export default {
index() {
return notesConnection.find({}).toArray();
},
 create(newNote) {
return client.db("noteTaker").collection("notes").insertOne(newNote);
}
}
```

### GET 
Print 1 note (instead of all the notes)
In the controller we can use .findOne(id)
```
show(id) {
return notesConnection.findOne(ObjectId(id));
}
```

Adding to routes, we'll need to use a dynamic path. We'll also need to add in params 
```
router.get("/notes/:id", async (req, res) => {
try {
const note = await noteController.show(req.params.id);
res.json(note);
} catch(error) {
res.status(400).send(error);
}
})
```

### DELETE
Delete a note... going to skip the routes since this is a review.
In the controller, we'll need to use .deleteOne and pass in the id as an object.
```
delete(id) {
 return notesConnection.deleteOne({ _id: ObjectId(id) });
}
```