Skip to content

Commit 39d46af

Browse files
authored
Merge pull request #4 from ReCoded-Org/crud-and-data-models
Module 3: CRUD and data models
2 parents 65f8f3b + 2ea52ff commit 39d46af

File tree

8 files changed

+543
-1
lines changed

8 files changed

+543
-1
lines changed
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
# curriculum-backend-readings
1+
# Module 3: CRUD and Data Models
1.51 MB
Loading
Lines changed: 224 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,224 @@
1+
# Introduction To Database Schemas
2+
3+
A database schema is a blueprint or architecture of how our data will look. It doesn’t hold data itself, but instead describes the shape and structure of the data and how it might be related to other data.
4+
5+
For example, this is a `customer` schema in MongoDB using Mongoose.
6+
7+
```js
8+
const mongoose = require("mongoose");
9+
10+
const customer = new mongoose.Schema({
11+
name: {
12+
type: String,
13+
required: true,
14+
},
15+
zipcode: {
16+
type: Number,
17+
},
18+
});
19+
20+
module.exports = mongoose.model("customer", customer);
21+
```
22+
23+
The same `customer` schema in PostgreSQL using [Sequelize](https://sequelize.org/).
24+
25+
```js
26+
const Sequelize = require("sequelize");
27+
28+
module.exports = (sequelize, DataTypes) => {
29+
const Customer = sequelize.define("customer", {
30+
name: {
31+
type: DataTypes.STRING,
32+
allowNull: false,
33+
},
34+
zipcode: {
35+
type: DataTypes.INTEGER,
36+
},
37+
});
38+
return Customer;
39+
};
40+
```
41+
42+
We can see that the schema definition for the `customer` has a `name` that is type `string` and a `zipcode` that is of type `number`. The `name` field is mandatory and cannot be empty.
43+
44+
Another concept that can be confused with the database schema is the "Model".
45+
Models are fancy constructors compiled from schema definitions. An instance of a model is called a document. Models are responsible for creating and reading documents from the underlying MongoDB database.
46+
47+
## Introduction to CRUD operations
48+
49+
When we are building APIs, we want our models to provide four basic types of functionality. The model must be able to Create, Read, Update, and Delete resources. Computer scientists often refer to these functions by the acronym CRUD. A model should have the ability to perform at most these four functions in order to be complete.
50+
51+
### CRUD in REST
52+
53+
In a REST environment, CRUD often corresponds to the [HTTP request methods](https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods) `POST`, `GET`, `PUT`, and `DELETE`, respectively. These are the fundamental elements of a persistent storage system.
54+
55+
For example, imagine we are working with a system that is keeping track of meals and their corresponding prices for a restaurant. Let’s look at how we would implement CRUD operations.
56+
57+
First of all, we need to define our food item schema (we will use mongoose for that), and let's call it "dish".
58+
59+
```js
60+
const mongoose = require("mongoose");
61+
62+
const dish = new mongoose.Schema({
63+
title: {
64+
type: String,
65+
required: true,
66+
},
67+
image: {
68+
type: String,
69+
required: true,
70+
},
71+
tags: [String],
72+
});
73+
74+
module.exports = mongoose.model("dish", dish);
75+
```
76+
77+
#### Create
78+
79+
To create resources in a REST environment, we most commonly use the HTTP POST method. POST creates a new resource of the specified resource type.
80+
Imagine that we are adding a new food item to the stored list of dishes for this restaurant, and the dish objects are stored in a dishes resource.
81+
82+
Note: Use `POST` when you want to add a child resource under resources collection.
83+
84+
Request:
85+
86+
`POST http://www.myrestaurant.com/api/dishes/`
87+
88+
We will need to send the dish data too as an object in the body.
89+
90+
For example
91+
92+
```js
93+
{
94+
title: "Lasagna",
95+
image: "www.food.com/lasagna.jpg",
96+
tags: ["simple", "classic"]
97+
}
98+
99+
```
100+
101+
On the backend side, our express route will be
102+
103+
```js
104+
router.post("/dishes", async (req, res) => {
105+
// get the data we sent in the body
106+
const dishData = req.body;
107+
try {
108+
// using the create() method with Mongoose will insert the data we sent in the body to our MongoDB database
109+
// and return an object of that data when done
110+
const newDish = await DishModel.create(dishData);
111+
// then, we return the new created dish object
112+
res.status(201).json(newDish);
113+
} catch (err) {
114+
res.status(422).json({ message: err.message });
115+
}
116+
});
117+
})
118+
```
119+
120+
#### Read
121+
122+
To read resources in a REST environment, we use the GET method. In practice, reading a resource shouldn't change any information - it should only retrieve it.
123+
124+
To read resources in a REST environment, we use the GET method. Reading a resource should never change any information - it should only retrieve it. REST itself is more like a set of guidelines. Technically, you can change data in a `GET` request, but since we are creating a RESTful API, you shouldn't do that. Having a GET request that updates data in your database would be confusing to the users of your API and violate the expected behavior of REST.
125+
126+
Request:
127+
128+
`GET http://www.myrestaurant.com/api/dishes/`
129+
130+
The express route for getting all dished will be
131+
132+
```js
133+
router.get("/dishes", async (_, res) => {
134+
// here, we are using the find() to return all dishes from our MongoDB database
135+
// find() will return an array of dish objects
136+
const posts = await DishModel.find();
137+
res.json(posts);
138+
});
139+
```
140+
141+
#### Update
142+
143+
PUT is the HTTP method used for the CRUD operation, Update.
144+
So if the price of Avocado Toast has gone up, we should go into the database and update that information using PUT.
145+
146+
Note: Use `PUT` when you want to modify a singular resource which is already a part of resources collection. `PUT` replaces the resource with the data you send in its entirety.
147+
148+
Request:
149+
150+
`PUT http://www.myrestaurant.com/dishes/:id`
151+
152+
We will need to send the new dish data too as an object.
153+
154+
For example
155+
156+
```js
157+
{
158+
title: "New dish title",
159+
image: "www.food.com/dish.jpg",
160+
tags: ["simple", "classic"]
161+
}
162+
```
163+
164+
Note that when using Mongoose you don't have to send all the object fields, you can only send the ones that got changed.
165+
166+
For example, we can only send the title.
167+
168+
```js
169+
{
170+
title: "New dish title",
171+
}
172+
```
173+
174+
Respectively, our express route for both these examples will be
175+
176+
```js
177+
router.put("/dishes/:id", async (req, res) => {
178+
// we need the dish id in order to tell Mongoose which dish to update in our database
179+
const { id } = req.params;
180+
try {
181+
// the findByIdAndUpdate() will make sure the dish exist before updating it
182+
const updatedDish = await DishModel.findByIdAndUpdate(id, req.body, {
183+
// the { new: true } here is just to tell Mongoose we want the newely updated dish back
184+
new: true,
185+
});
186+
// we return the updated dish as a JSON object to the user
187+
res.json(updatedDish);
188+
} catch (err) {
189+
res.status(422).json({ message: err.message });
190+
}
191+
});
192+
```
193+
194+
#### Delete
195+
196+
The CRUD operation Delete corresponds to the HTTP method DELETE. It is used to remove a resource from the system.
197+
Let’s say that the world avocado shortage has reached a critical point, and we can no longer afford to serve this modern delicacy at all. We should go into the database and delete the item that corresponds to **Avocado Toast**, which we know has an `id` of 1223.
198+
199+
Request:
200+
201+
`DELETE http://www.myrestaurant.com/dishes/:id`
202+
203+
The express route for this deleting request can be
204+
205+
```js
206+
router.delete("/dishes/:id", async (req, res) => {
207+
const { id } = req.params;
208+
try {
209+
const dish = await PostModel.findByIdAndDelete(id);
210+
// the status code is 204 because we are not returning data or entities
211+
return res.status(204).json({ success: true });
212+
} catch (err) {
213+
res.status(422).json({ message: err.message });
214+
}
215+
});
216+
```
217+
218+
---
219+
220+
## References
221+
222+
- https://restfulapi.net/
223+
- https://www.educative.io/blog/crud-operations#what
224+
- https://www.educative.io/blog/what-are-database-schemas-examples#types
Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
# Principles Of Setting up Your Schema
2+
3+
Poorly designed databases can cause many problems, including wasting resources, making maintenance difficult, and hindering performance. That's why having a great database schema design is a crucial part of effective data management.
4+
By defining categories of data and relationships between those categories, database schema design makes data much easier to retrieve, consume, manipulate, and interpret.
5+
Without a clean, efficient, consistent database schema, you’ll struggle to make the best use of your enterprise data. For example, the same data might be duplicated in multiple locations—or even worse, might be inconsistent between these locations.
6+
7+
## Type of database
8+
9+
Most developers don't see the difference between relational database schema and MongoDB schema, but in reality, it is not the same
10+
11+
<img src="../assets/relationalDBmeme.png" alt="meme" width="400"/>
12+
13+
In a nutshell, in relational databases, models are usually independent of queries, there is no duplication of data as data will _mostly_ be separated into different tables, and it is rigid, you will have to define types and fields for your schema beforehand.
14+
15+
In the other hand, `MongoDB`, you have more flexibility, there are no rules, documents can have new data or fields at any point of time, no need to define types.
16+
17+
### Embedding vs. Referencing
18+
19+
One of the key points to establish a good schema design (especially, if you are using MongoDB) is whether to embed or reference your data.
20+
21+
#### Embedding
22+
23+
When a collection has a document, and, this document contains another document, another document contains another sub-document, and so on. This is called embedding or nesting.
24+
25+
#### When to Embed
26+
27+
- To retrive all data in a single query.
28+
- Avoid expense JOINs or $lookups.
29+
- Update all data with a single operation.
30+
- In one-to-one or one-to-many relationships between documents.
31+
32+
#### Referencing
33+
34+
When a value of a field in your table or collection referes to a value of another field in another table or collection.
35+
36+
#### When to Reference
37+
38+
- If you need smaller documents or tables, your data will be separated across multiple documents or tables.
39+
- No duplicate of data.
40+
- To reduce accessed data not accessed on every query.
41+
- In many-to-many relationships between tables and documents.
42+
43+
In general, there are few **rules** you can follow to better design your schema:
44+
45+
##### 1. Favor embedding over referencing unless there is a compelling reason not to.
46+
47+
Embedded documents are an efficient and clean way to store related data, especially data that's regularly accessed together. The more often a given workload can retrieve a single document and have all the data it needs, the more consistently high-performance your application will be.
48+
49+
##### 2. Needing to access an object on its own is a compelling reason not to embed.
50+
51+
Separate data that can be referred to from multiple places into its own collection.
52+
This is not so much a "storage space" issue as it is a "data consistency" issue. If many records will refer to the same data it is more efficient and less error prone to update a single record and keep references to it in other places.
53+
54+
##### 3. Avoid JOINs and $lookups if they can be avoided, but don't be afraid if they can provide a better schema design.
55+
56+
Having a JOIN or `$lookup` means you are doing some kind of search in your database for the corresponding field and that operation takes time. So if you embed your data in a single object, you will spare this operation, and your query can be much faster and cleaner.
57+
58+
##### 4. How you model your data depends _entirely_ on your particular application's data access patterns.
59+
60+
This means that no matter what you read or watch, you may still need to make few changes to your schema based on your own use case and application.
61+
62+
---
63+
64+
## References
65+
66+
- https://www.mongodb.com/developer/article/mongodb-schema-design-best-practices/
67+
- https://www.xplenty.com/blog/complete-guide-to-database-schema-design-guide/
Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
# Model View Controller (MVC)
2+
3+
## Introduction to MVC projects
4+
5+
When beginning a new project (especially, when using Express), there are several different methods that can be used to set up the overall file structure and flow. One of the most commonly used architectural patterns is called MVC. This acronym stands for "Model, View, Controller".
6+
This pattern is favored because of its alignment with the computer science design principle, [**separation of concerns**](https://en.wikipedia.org/wiki/Separation_of_concerns). By dividing up responsibilities within our file structure, for example, we can have our db connection work in one file and api routes in another file, ...etc.
7+
8+
```
9+
app-name-here
10+
|- Controllers
11+
|- db
12+
|- Models
13+
|- node_modules
14+
.gitignore
15+
index.js
16+
package.json
17+
package-lock.json
18+
```
19+
20+
### Components Of MVC
21+
22+
**Model:** This consists of the structure of our data and handle the database.
23+
24+
**View:** The part of our application which is shown to the user.
25+
26+
**Controller:** Controller has all the logic to control and respond to the action, the user performs using the views.
27+
28+
### Models
29+
30+
In this folder, you can write the functionality & logics related to the database (if you aren't using ORM) like insert, fetch, update, delete queries. It takes the query request from the controller & sends the response back to the controller.
31+
The naming convention for the model files is: `name-here-model.js`.
32+
33+
Here’s an example model using JavaScript and Mongoose.
34+
35+
```js
36+
// post-model.js
37+
38+
const mongoose = require("mongoose");
39+
40+
const post = new mongoose.Schema({
41+
title: {
42+
type: String,
43+
required: true,
44+
},
45+
body: {
46+
type: String,
47+
required: true,
48+
},
49+
createdAt: {
50+
type: Date(),
51+
},
52+
author: {
53+
type: String,
54+
required: true,
55+
},
56+
});
57+
58+
module.exports = mongoose.model("Post", post);
59+
```
60+
61+
### Views
62+
63+
In this folder, you can write HTML code for displaying a web page on the web browser. You can send the data from the controller to view for displaying data dynamically.
64+
In a back-end application, views are usually not implemented and rather we create a front-end app using maybe `React` to call our `api` end-points to manipulate and dispaly the data in the back-end.
65+
66+
### Controllers
67+
68+
Controllers are the layer between the Model and the View. the views can use the controllers to `add`, `read`, `delete`, ...etc data.
69+
In controllers, you can write the functionality & logic to develop dynamic web applications. It takes the data request from the views & sends it to the model and sends the response back to the views.
70+
The naming convention for the model files is: `name-here-controller.js`.
71+
72+
Here is an example:
73+
74+
```js
75+
// post-controller.js
76+
77+
const express = require('express');
78+
const router = express.Router();
79+
const Post = require('../models/post-model.js')
80+
81+
router.get('/posts', (req, res) => {
82+
Post.find({})
83+
.then((posts) => {
84+
res.json(posts);
85+
})
86+
.catch(console.error)
87+
})
88+
});
89+
```
90+
91+
---
92+
93+
## References
94+
95+
- https://medium.com/geekculture/mvc-architecture-with-express-server-e35aedfe7889
96+
- https://codingstatus.com/express-mvc-structure/

0 commit comments

Comments
 (0)