# 12/8 部課
## Review: Workflow
Ref: https://www.youtube.com/watch?app=desktop&v=YGxrvHGCJ2Y

Frontend to Backend: Application layer(應用層) under TCP/IP model
List of Protocols in Application layer: https://www.geeksforgeeks.org/application-layer-protocols-in-tcp-ip/
### HTTP requests
1. Request Line

2. HTTP headers

3. Message body
:::info
**GET** Method usually *does not include* message body.
:::
> Message bodies are appropriate for some request methods and inappropriate for others. For example, a request with the POST method, which sends input data to the server, has a message body containing the data. A request with the GET method, which asks the server to send a resource, does not have a message body.
### HTTP response
1. Status line
2. HTTP headers

3. Message body
For the example above, it will return corresponding html script.
## Database
### What is a database?
> A database, in the most general sense, is an *organized collection of data*. More specifically, a database is an **electronic system** that allows data to be easily accessed, manipulated and updated.
> When people refer to a “database” they’re often talking about a computer program that allows them to *interact with their database*. These programs, known more formally as a **database management system (DBMS)**, are often installed on a virtual private server and accessed remotely.
### Relational Databases(RDBMSs)
- Data are stored by multiple **tables**
- A table is constructed with a set of tuples, or rows in a table, with each tuple sharing a set of attributes, or columns
- There exists some explicit relations between data, but only useful if you can retrieve it.

(ref: https://www.digitalocean.com/community/conceptual-articles/an-introduction-to-databases)
- Uses **Structured Query Language(SQL)** to manage and query data
- Examples: MySQL, PostgreSQL, SQLite, ...
Problems with RDBMS:
- Not always every set of data exist explicit relations with each other
- Must specify unique attribute
### Non-relational Databases(NoSQL databases)
- Does not implement SQL
- Not need relations, being more flexible with data storing
- Difficulty of choosing NoSQL


- Redis: Key-Value Databases
- MongoDB: Document-Oriented Databases
### Object Relational Mapping (ORM)
> When interacting with a database using OOP languages, you'll have to perform different operations like creating, reading, updating, and deleting (CRUD) data from a database. By design, you use **SQL** for performing these operations in relational databases.
> While using SQL for this purpose isn't necessarily a bad idea, the ORM and ORM tools help simplify the interaction between relational databases and different OOP languages.
For example, if we want to find a todo item named "buying an apple" and haven't done(done = False) in `Todo` database, we can access it by using ORM syntax:
```javascript=
Todo.find ({ name: 'buying an apple', done: { false }})
```
Using SQL syntax:
```sql=
SELECT * FROM Todos WHERE name='buying an apple' AND done=FALSE;
```
### MongoDB
- NoSQL, Document-Oriented
:::info
Document-Oriented: Mixture of Relational & Key-Value Databases
:::
- Format
```javascript=
Todo.find()[0].username
```
```jsonld=
{
"_id": { "$oid": "6572e1cef219bca05511d230" },
"id": { "$numberInt": "1" },
"username": "admin",
"passwd": "$2a$10$/sbmKQjOpqfeeZ1gFEyaauNC5GxNL6yTgJP/AIbGCN9DpyxOMv9Ou",
"identity": "Admin",
"events": [],
"isLoggedIn": false,
"loggedInAt": { "$date": { "$numberLong": "1672993352831" } },
"__v": { "$numberInt": "0" }
}
```
### MongoDB Atlas
- Free service from MongoDB official
https://lyunotes.blogspot.com/2020/11/day12-mongodb-atlas.html
https://www.mongodb.com/
https://www.mongodb.com/atlas/database
### Start !!!
#### Step 1: Connection
In `server.js`:
```javascript=
const mongoose = require("mongoose");
require("dotenv").config();
const { MONGO_USERNAME, MONGO_PASSWORD } = process.env;
const uri = `mongodb+srv://${MONGO_USERNAME}:${MONGO_PASSWORD}@cluster0.ogm4i.mongodb.net/myFirstDatabase?retryWrites=true&w=majority`;
// this can be copied in MongoDB Atlas
mongoose
.connect(uri, {
useNewUrlParser: true,
useUnifiedTopology: true,
});
const db = mongoose.connection;
db.on("err", (err) => {
console.error(err);
});
db.on("open", () => {
console.log("Successfully connect to mongoDB");
});
```
in `.env`:
```
MONGO_USERNAME=
MONGO_PASSWORD=
```
Install `dotenv-defaults` if Error
```
npm install dotenv
```
#### Step 2: Define Schema
Create a `model` directory
In `user.js`:
```javascript=
const mongoose = require("mongoose");
const Schema = mongoose.Schema;
const UserSchema = new Schema({
id: {
type: Number,
required: [true, "Id field is required."],
},
name: {
type: String,
required: [true, "Name field is required."],
},
});
// Creating a table within database with the defined schema
const User = mongoose.model("User", UserSchema);
// Exporting table for querying and mutating
module.exports = User;
```
In `server.js`: Import User Schema
```javascript=
const User = require("./model/user");
```
#### Step 3: Define Mutation Function
In `server.js`:
```javascript=
const saveUser = async (id, name) => {
const existing = await User.findOne({ name: name });
if (existing) {
console.log(`Username ${name} already exists!!`);
return;
}
try {
const newUser = new User({ id, name });
console.log("Created user", newUser);
await newUser.save();
console.log("Successfully saved");
return;
} catch (e) {
throw new Error("User creation error: " + e);
}
};
const DeleteDB = async () => {
try {
await User.deleteMany({});
console.log("Database deleted");
} catch (e) {
throw new Error("Database deletion failed");
}
};
```
:::info
:book: Mutation: to mutate -> to modify data (CRUD operations)
:::
#### Step 4: Define Route to call Mutation Functions
In `server.js`
```javascript=
const router = require("router");
router.post("/saveuser", saveUser)
// More Routers
app.use("/", router)
```
Or just
```javascript=
app.route("/saveuser")
.get((req, res) => {
// do something
})
```