You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
- 1.2 [Principles of setting up your schema [R]](../module3-crud-and-data-models/r1.2-principles-of-setting-up-your-schema/README.md)
18
+
19
+
- 1.3 [Setup project schema using MongoDB [L]](../module3-crud-and-data-models/r1.3-setup-project-schema/README.md)
20
+
21
+
- 1.4 [Setup project schema using Mongoose [L]](../module3-crud-and-data-models/r1.4-setup-project-schema-using-mongoose/README.md)
22
+
23
+
- 1.5 [Setup project schema using Mongoose with embedding [L]](../module3-crud-and-data-models/r1.5-setup-project-schema-using-mongoose-embedding/README.md)
24
+
25
+
- 2 [Models and Controllers in Mongoose [R]](../module3-crud-and-data-models/r2-models-and-controllers-in-mongoose/README.md)
26
+
27
+
- 2.1 [CRUD with Mongoose [L]](../module3-crud-and-data-models/r2.1-crud-with-mongoose/README.md)
28
+
29
+
- 3 [Custom model methods [R]](../module3-crud-and-data-models/r3-building-custom-methods-on-mongoose/README.md)
We have learned how to store and query data in different types of databases. In order to connect our database operations with our API code, we need to put together a database schema. The objectives of this lesson are:
3
+
1. Getting familiar with database schemas using an ORM/ODM
4
+
2. Getting familiar with CRUD operations in our APIs
2
5
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
+
## Introduction To Database Schemas
7
+
A database schema is a blueprint or architecture of how our data will look. It doesn't hold any data itself, but instead describes the shape and structure of the data and how it might be related to other data.
6
8
9
+
For example, this is a `customer` schema in MongoDB using [Mongoose](https://mongoosejs.com/).
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
46
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.
47
+
### Models
48
+
Sometimes the term "schema" and "model" can be confused with each other. Take a look at [this Stackoverflow discussion](https://stackoverflow.com/questions/25093452/difference-between-data-model-and-database-schema-in-dbms) about the difference between the two.
49
+
Our favorite description is this one - "The database schema is one that contains list of attributes and instructions to tell the database engine how data is organised whereas Data model is a collection of conceptional tools for describing data, data-relationship and consistency constraints."
46
50
47
-
## Introduction to CRUD operations
51
+
Take a look again at the Mongoose example from above. You can see that first we define a schema using the `mongoose.Schema()` function and then we define a model using `mongoose.model()` function which takes the schema as a parameter. From this we can tell that the schema is only a representation of the data structure, however it is the model which makes use of this structure to perform the actual operations on the database because it has all the necessary underlying tools for this. We will look at this in practice in some of the next examples.
48
52
53
+
From the [Mongoose documentation](https://mongoosejs.com/docs/models.html) - "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."
54
+
55
+
## Introduction to CRUD operations
49
56
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
57
51
58
### 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.
59
+
We already know that 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
60
55
61
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
62
57
63
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
64
```js
60
65
constmongoose=require("mongoose");
61
66
@@ -69,66 +74,52 @@ const dish = new mongoose.Schema({
69
74
required:true,
70
75
},
71
76
tags: [String],
77
+
price:Number
72
78
});
73
79
74
80
module.exports=mongoose.model("dish", dish);
75
81
```
76
82
77
83
#### Create
84
+
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. 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.
78
85
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:
86
+
Note: Use `POST` when you want to add a child resource under resources collection.)
85
87
88
+
**Request**:
86
89
`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
-
90
+
We will need to send the dish data too as an object in the body. For example:
92
91
```js
93
92
{
94
93
title:"Lasagna",
95
94
image:"www.food.com/lasagna.jpg",
96
-
tags: ["simple", "classic"]
95
+
tags: ["simple", "classic"],
96
+
price:10
97
97
}
98
-
99
98
```
100
-
101
-
On the backend side, our express route will be
102
-
99
+
**Code**:
103
100
```js
104
101
router.post("/dishes", async (req, res) => {
105
102
// get the data we sent in the body
106
103
constdishData=req.body;
107
104
try {
108
105
// 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
106
constnewDish=awaitDishModel.create(dishData);
111
-
//then, we return the new created dish object
107
+
//and return the newly created data when done
112
108
res.status(201).json(newDish);
113
109
} catch (err) {
114
110
res.status(422).json({ message:err.message });
115
111
}
116
112
});
117
-
})
118
113
```
119
114
120
115
#### Read
121
-
122
116
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
117
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:
118
+
Note: Technically, you can change data in a `GET` request, but since you are creating a RESTful API, you shouldn't do that and follow the REST guidelines. 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.
127
119
120
+
**Request**:
128
121
`GET http://www.myrestaurant.com/api/dishes/`
129
-
130
-
The express route for getting all dished will be
131
-
122
+
**Code**:
132
123
```js
133
124
router.get("/dishes", async (_, res) => {
134
125
// here, we are using the find() to return all dishes from our MongoDB database
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
134
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.
135
+
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.
147
136
148
-
Request:
137
+
So if the price of Avocado Toast has gone up, we should go into the database and update that information using PUT.
149
138
139
+
**Request**:
150
140
`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
-
141
+
We will need to send the new dish data too as an object. For example:
156
142
```js
157
143
{
158
-
title:"New dish title",
144
+
title:"Avocado Toast",
159
145
image:"www.food.com/dish.jpg",
160
-
tags: ["simple", "classic"]
146
+
tags: ["simple", "breakfast"],
147
+
price:100
161
148
}
162
149
```
163
150
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
-
151
+
Note that when using Mongoose you don't have to send all the object fields, you can only send the ones that got changed. For example, we can only send the title:
168
152
```js
169
153
{
170
-
title:"New dish title",
154
+
price:"100"
171
155
}
172
156
```
173
157
174
-
Respectively, our express route for both these examples will be
175
-
158
+
**Code**:
176
159
```js
177
160
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
161
+
// we need the dish id in order to tell mongoose which dish to update in our database
179
162
const { id } =req.params;
180
163
try {
181
-
// the findByIdAndUpdate() will make sure the dish exist before updating it
164
+
// the findByIdAndUpdate() will make sure the dish exists before updating it
165
+
// the { new: true } here is just to tell mongoose we want the newly updated dish back after the update is complete
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
179
199
-
Request:
180
+
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 let's say we know has an `id` of 1223.
200
181
182
+
**Request**:
201
183
`DELETE http://www.myrestaurant.com/dishes/:id`
202
184
203
-
The express route for this deleting request can be
One of the most popular software design patterns used for web development is the MVC pattern. The objectives of this lesson are:
3
+
1. Getting familiar with the MVC pattern
4
+
2. Understanding the use of models, views and controllers
2
5
3
6
## Introduction to MVC projects
4
-
5
7
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
+
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). We can divide up functional responsibilities within our file structure and separate business logic from display handling. For example, we can have our database connection in one file and API routes in another file.
10
+
11
+
A common MVC project structure would look something like this:
8
12
```
9
13
app-name-here
10
14
|- controllers
11
15
|- db
12
16
|- models
13
17
|- node_modules
18
+
|- views
14
19
.gitignore
15
20
index.js
16
21
package.json
17
22
package-lock.json
18
23
```
19
24
20
25
### 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.
26
+
1.**Model:** As we've read in the previous lesson, this consists of the structure of our data and handles operations to be performed on the database.
27
+
2.**View:** The part of our application which handles everything to be shown to the user.
28
+
3.**Controller:** This has all the logic to control and respond to the requests which the user is sending by interacting with the views. The controller routes commands to the model and view parts.
27
29
28
30
### Models
31
+
In your `models` folder, you can write the functionality & logic related to the database (if you aren't using an ORM) like insert, fetch, update and delete queries. It takes the query request from the controller & sends the result of the database operation back to the controller. The general naming convention for the model files is: `name-here-model.js`.
29
32
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.
In your `views` 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.
62
+
63
+
You have already seen this in practice in Module 1 where you stored EJS templates in a folder called `views`. You even assigned this folder as the views folder to Express, by executing:
64
+
```js
65
+
app.set("views", "views")
66
+
```
62
67
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.
68
+
In a backend application, views are usually not implemented and rather we create a frontend application using maybe React to call our backend API endpoints for data fetch and manipulation requests.
65
69
66
70
### 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
+
In your `controllers` folder, you can write the functionality & logic to develop dynamic web applications by handling requests and sending responses. It takes the data request from the views & sends it to the model. After receiving the result from the model, it then sends the response back to the views. If there are no views implemented, then it receives and responds to requests from one or more clients. The naming convention for the controller files is: `name-here-controller.js`.
You can read more about the MVC pattern in the MDN Web Docs [here](https://developer.mozilla.org/en-US/docs/Glossary/MVC). You can also read on examples of setting up MVC projects in Node.js [here](https://www.sitepoint.com/node-js-mvc-application/) and [here](https://medium.com/@ipenywis/what-is-the-mvc-creating-a-node-js-express-mvc-application-da10625a4eda).
92
92
93
-
## References
93
+
So far we had been implementing most of our logic within a single JS file in previous assignments. Going forward as we learn to build more full-fledged backend applications, we will be following the MVC pattern in our project files structure.
0 commit comments