Skip to content

Commit 3162f04

Browse files
committed
first commit
0 parents  commit 3162f04

File tree

9 files changed

+422
-0
lines changed

9 files changed

+422
-0
lines changed

.gitignore

+2
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
node_modules
2+
package-lock.json

README.md

+131
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,131 @@
1+
# Node.js PostgreSQL CRUD example with Express Rest APIs
2+
3+
Full Article with implementation:
4+
> [Node.js PostgreSQL CRUD example with Express Rest APIs](https://bezkoder.com/node-express-sequelize-postgresql/)
5+
6+
We will build Rest Apis that can create, retrieve, update, delete and find Tutorials by title.
7+
8+
The following table shows overview of the Rest APIs that will be exported:
9+
10+
- GET `api/tutorials` get all Tutorials
11+
- GET `api/tutorials/:id` get Tutorial by id
12+
- POST `api/tutorials` add new Tutorial
13+
- PUT `api/tutorials/:id` update Tutorial by id
14+
- DELETE `api/tutorials/:id` remove Tutorial by id
15+
- DELETE `api/tutorials` remove all Tutorials
16+
- GET `api/tutorials/published` find all published Tutorials
17+
- GET `api/tutorials?title=[kw]` find all Tutorials which title contains 'kw'
18+
19+
## Demo Video
20+
This is our Node.js PostgreSQL CRUD example using Express & Sequelize application demo, test Rest Apis with Postman.
21+
22+
[![Node.js PostgreSQL CRUD example Github](http://img.youtube.com/vi/x1pZHN_sjGk/0.jpg)](http://www.youtube.com/watch?v=x1pZHN_sjGk "Node.js PostgreSQL CRUD example Github")
23+
24+
### Test the APIs
25+
Run our Node.js application with command: `node server.js`.
26+
27+
Using Postman, we're gonna test all the Apis above.
28+
29+
- Create a new Tutorial using `POST /tutorials` Api
30+
31+
![node-js-postgresql-crud-example-create](https://dev-to-uploads.s3.amazonaws.com/i/hqvz8ra9p21z927iwzph.png)
32+
33+
After creating some new Tutorials, you can check PostgreSQL table:
34+
```testdb=# select * from tutorials;
35+
id | title | description | published | createdAt | updatedAt
36+
----+-------------+-------------------+-----------+----------------------------+----------------------------
37+
1 | Node Tut #1 | Tut#1 Description | f | 2020-01-29 10:42:57.121+07 | 2020-01-29 10:42:57.121+07
38+
2 | Node Tut #2 | Tut#2 Description | f | 2020-01-29 10:43:05.131+07 | 2020-01-29 10:43:05.131+07
39+
3 | Node Tut #3 | Tut#3 Description | f | 2020-01-29 10:43:48.028+07 | 2020-01-29 10:43:48.028+07
40+
4 | Js Tut #4 | Tut#4 Desc | f | 2020-01-29 10:45:40.016+07 | 2020-01-29 10:45:40.016+07
41+
5 | Js Tut #5 | Tut#5 Desc | f | 2020-01-29 10:45:44.289+07 | 2020-01-29 10:45:44.289+07
42+
```
43+
44+
- Retrieve all Tutorials using `GET /tutorials` Api
45+
46+
![node-js-postgresql-crud-example-retrieve-all](https://dev-to-uploads.s3.amazonaws.com/i/m9razjm1njgww58er3as.png)
47+
48+
- Retrieve a single Tutorial by id using `GET /tutorials/:id` Api
49+
50+
![node-js-postgresql-crud-example-retrieve-one](https://dev-to-uploads.s3.amazonaws.com/i/0kuojvc596i5u423od2b.png)
51+
52+
- Update a Tutorial using `PUT /tutorials/:id` Api
53+
54+
![node-js-postgresql-crud-example-update](https://dev-to-uploads.s3.amazonaws.com/i/3buqfz0by0lu2z4kf3uq.png)
55+
56+
Check `tutorials` table after some rows were updated:
57+
```testdb=# select * from tutorials;
58+
id | title | description | published | createdAt | updatedAt
59+
----+----------------+-------------------+-----------+----------------------------+----------------------------
60+
1 | Node Tut #1 | Tut#1 Description | f | 2020-01-29 10:42:57.121+07 | 2020-01-29 10:42:57.121+07
61+
3 | Node Tut #3 | Tut#3 Description | f | 2020-01-29 10:43:48.028+07 | 2020-01-29 10:43:48.028+07
62+
2 | Node Js Tut #2 | Tut#2 Description | t | 2020-01-29 10:43:05.131+07 | 2020-01-29 10:51:55.235+07
63+
4 | Js Tut #4 | Tut#4 Desc | t | 2020-01-29 10:45:40.016+07 | 2020-01-29 10:54:17.468+07
64+
5 | Js Tut #5 | Tut#5 Desc | t | 2020-01-29 10:45:44.289+07 | 2020-01-29 10:54:20.544+07
65+
```
66+
67+
- Find all Tutorials which title contains 'js': `GET /tutorials?title=js`
68+
69+
![node-js-postgresql-crud-example-search](https://dev-to-uploads.s3.amazonaws.com/i/u2hbmz5r35o7uo09y3z5.png)
70+
71+
- Find all published Tutorials using `GET /tutorials/published` Api
72+
73+
![node-js-postgresql-crud-example-search-status](https://dev-to-uploads.s3.amazonaws.com/i/dbo753wfqibt0b93d82d.png)
74+
75+
- Delete a Tutorial using `DELETE /tutorials/:id` Api
76+
77+
![node-js-postgresql-crud-example-delete-one](https://dev-to-uploads.s3.amazonaws.com/i/pyos3wq4tchb8ixuyj1c.png)
78+
79+
Tutorial with id=4 was removed from `tutorials` table:
80+
```testdb=# select * from tutorials;
81+
id | title | description | published | createdAt | updatedAt
82+
----+----------------+-------------------+-----------+----------------------------+----------------------------
83+
1 | Node Tut #1 | Tut#1 Description | f | 2020-01-29 10:42:57.121+07 | 2020-01-29 10:42:57.121+07
84+
3 | Node Tut #3 | Tut#3 Description | f | 2020-01-29 10:43:48.028+07 | 2020-01-29 10:43:48.028+07
85+
2 | Node Js Tut #2 | Tut#2 Description | t | 2020-01-29 10:43:05.131+07 | 2020-01-29 10:51:55.235+07
86+
5 | Js Tut #5 | Tut#5 Desc | t | 2020-01-29 10:45:44.289+07 | 2020-01-29 10:54:20.544+07
87+
```
88+
89+
- Delete all Tutorials using `DELETE /tutorials` Api
90+
91+
![node-js-postgresql-crud-example-delete-all](https://dev-to-uploads.s3.amazonaws.com/i/ga42747jorssl20ywyug.png)
92+
93+
Now there are no rows in `tutorials` table:
94+
```testdb=# select * from tutorials;
95+
id | title | description | published | createdAt | updatedAt
96+
----+-------+-------------+-----------+-----------+-----------
97+
```
98+
99+
For more detail, please visit:
100+
> [Node.js PostgreSQL CRUD example with Express Rest APIs](https://bezkoder.com/node-express-sequelize-postgresql/)
101+
102+
> [Node.js Express Pagination with PostgreSQL example](https://bezkoder.com/node-js-pagination-postgresql/)
103+
104+
Security:
105+
> [Node.js JWT Authentication & Authorization with PostgreSQL example](https://bezkoder.com/node-js-jwt-authentication-postgresql/)
106+
107+
Associations:
108+
> [Sequelize Associations: One-to-Many Relationship example](https://bezkoder.com/sequelize-associate-one-to-many/)
109+
110+
> [Sequelize Associations: Many-to-Many Relationship example](https://bezkoder.com/sequelize-associate-many-to-many/)
111+
112+
Fullstack:
113+
> [Vue + Node.js + Express + PostgreSQL example](https://bezkoder.com/vue-node-express-postgresql/)
114+
115+
> [React + Node.js + Express + PostgreSQL example](https://bezkoder.com/react-node-express-postgresql/)
116+
117+
> [ANgular 8 + Node.js + Express + PostgreSQL example](https://bezkoder.com/angular-node-express-postgresql/)
118+
119+
> [ANgular 10 + Node.js + Express + PostgreSQL example](https://bezkoder.com/angular-10-node-express-postgresql/)
120+
121+
> [ANgular 11 + Node.js + Express + PostgreSQL example](https://bezkoder.com/angular-11-node-js-express-postgresql/)
122+
123+
## Project setup
124+
```
125+
npm install
126+
```
127+
128+
### Run
129+
```
130+
node server.js
131+
```

app/config/db.config.js

+13
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
module.exports = {
2+
HOST: "localhost",
3+
USER: "postgres",
4+
PASSWORD: "123",
5+
DB: "testdb",
6+
dialect: "postgres",
7+
pool: {
8+
max: 5,
9+
min: 0,
10+
acquire: 30000,
11+
idle: 10000
12+
}
13+
};
+146
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,146 @@
1+
const db = require("../models");
2+
const Tutorial = db.tutorials;
3+
const Op = db.Sequelize.Op;
4+
5+
// Create and Save a new Tutorial
6+
exports.create = (req, res) => {
7+
// Validate request
8+
if (!req.body.title) {
9+
res.status(400).send({
10+
message: "Content can not be empty!"
11+
});
12+
return;
13+
}
14+
15+
// Create a Tutorial
16+
const tutorial = {
17+
title: req.body.title,
18+
description: req.body.description,
19+
published: req.body.published ? req.body.published : false
20+
};
21+
22+
// Save Tutorial in the database
23+
Tutorial.create(tutorial)
24+
.then(data => {
25+
res.send(data);
26+
})
27+
.catch(err => {
28+
res.status(500).send({
29+
message:
30+
err.message || "Some error occurred while creating the Tutorial."
31+
});
32+
});
33+
};
34+
35+
// Retrieve all Tutorials from the database.
36+
exports.findAll = (req, res) => {
37+
const title = req.query.title;
38+
var condition = title ? { title: { [Op.iLike]: `%${title}%` } } : null;
39+
40+
Tutorial.findAll({ where: condition })
41+
.then(data => {
42+
res.send(data);
43+
})
44+
.catch(err => {
45+
res.status(500).send({
46+
message:
47+
err.message || "Some error occurred while retrieving tutorials."
48+
});
49+
});
50+
};
51+
52+
// Find a single Tutorial with an id
53+
exports.findOne = (req, res) => {
54+
const id = req.params.id;
55+
56+
Tutorial.findByPk(id)
57+
.then(data => {
58+
res.send(data);
59+
})
60+
.catch(err => {
61+
res.status(500).send({
62+
message: "Error retrieving Tutorial with id=" + id
63+
});
64+
});
65+
};
66+
67+
// Update a Tutorial by the id in the request
68+
exports.update = (req, res) => {
69+
const id = req.params.id;
70+
71+
Tutorial.update(req.body, {
72+
where: { id: id }
73+
})
74+
.then(num => {
75+
if (num == 1) {
76+
res.send({
77+
message: "Tutorial was updated successfully."
78+
});
79+
} else {
80+
res.send({
81+
message: `Cannot update Tutorial with id=${id}. Maybe Tutorial was not found or req.body is empty!`
82+
});
83+
}
84+
})
85+
.catch(err => {
86+
res.status(500).send({
87+
message: "Error updating Tutorial with id=" + id
88+
});
89+
});
90+
};
91+
92+
// Delete a Tutorial with the specified id in the request
93+
exports.delete = (req, res) => {
94+
const id = req.params.id;
95+
96+
Tutorial.destroy({
97+
where: { id: id }
98+
})
99+
.then(num => {
100+
if (num == 1) {
101+
res.send({
102+
message: "Tutorial was deleted successfully!"
103+
});
104+
} else {
105+
res.send({
106+
message: `Cannot delete Tutorial with id=${id}. Maybe Tutorial was not found!`
107+
});
108+
}
109+
})
110+
.catch(err => {
111+
res.status(500).send({
112+
message: "Could not delete Tutorial with id=" + id
113+
});
114+
});
115+
};
116+
117+
// Delete all Tutorials from the database.
118+
exports.deleteAll = (req, res) => {
119+
Tutorial.destroy({
120+
where: {},
121+
truncate: false
122+
})
123+
.then(nums => {
124+
res.send({ message: `${nums} Tutorials were deleted successfully!` });
125+
})
126+
.catch(err => {
127+
res.status(500).send({
128+
message:
129+
err.message || "Some error occurred while removing all tutorials."
130+
});
131+
});
132+
};
133+
134+
// find all published Tutorial
135+
exports.findAllPublished = (req, res) => {
136+
Tutorial.findAll({ where: { published: true } })
137+
.then(data => {
138+
res.send(data);
139+
})
140+
.catch(err => {
141+
res.status(500).send({
142+
message:
143+
err.message || "Some error occurred while retrieving tutorials."
144+
});
145+
});
146+
};

app/models/index.js

+23
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
const dbConfig = require("../config/db.config.js");
2+
3+
const Sequelize = require("sequelize");
4+
const sequelize = new Sequelize(dbConfig.DB, dbConfig.USER, dbConfig.PASSWORD, {
5+
host: dbConfig.HOST,
6+
dialect: dbConfig.dialect,
7+
8+
pool: {
9+
max: dbConfig.pool.max,
10+
min: dbConfig.pool.min,
11+
acquire: dbConfig.pool.acquire,
12+
idle: dbConfig.pool.idle
13+
}
14+
});
15+
16+
const db = {};
17+
18+
db.Sequelize = Sequelize;
19+
db.sequelize = sequelize;
20+
21+
db.tutorials = require("./tutorial.model.js")(sequelize, Sequelize);
22+
23+
module.exports = db;

app/models/tutorial.model.js

+15
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
module.exports = (sequelize, Sequelize) => {
2+
const Tutorial = sequelize.define("tutorial", {
3+
title: {
4+
type: Sequelize.STRING
5+
},
6+
description: {
7+
type: Sequelize.STRING
8+
},
9+
published: {
10+
type: Sequelize.BOOLEAN
11+
}
12+
});
13+
14+
return Tutorial;
15+
};

app/routes/turorial.routes.js

+28
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
module.exports = app => {
2+
const tutorials = require("../controllers/tutorial.controller.js");
3+
4+
var router = require("express").Router();
5+
6+
// Create a new Tutorial
7+
router.post("/", tutorials.create);
8+
9+
// Retrieve all Tutorials
10+
router.get("/", tutorials.findAll);
11+
12+
// Retrieve all published Tutorials
13+
router.get("/published", tutorials.findAllPublished);
14+
15+
// Retrieve a single Tutorial with id
16+
router.get("/:id", tutorials.findOne);
17+
18+
// Update a Tutorial with id
19+
router.put("/:id", tutorials.update);
20+
21+
// Delete a Tutorial with id
22+
router.delete("/:id", tutorials.delete);
23+
24+
// Delete all Tutorials
25+
router.delete("/", tutorials.deleteAll);
26+
27+
app.use("/api/tutorials", router);
28+
};

package.json

+27
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
{
2+
"name": "nodejs-express-sequelize-postgresql",
3+
"version": "1.0.0",
4+
"description": "Node.js Rest Apis with Express, Sequelize & PostgreSQL",
5+
"main": "server.js",
6+
"scripts": {
7+
"test": "echo \"Error: no test specified\" && exit 1"
8+
},
9+
"keywords": [
10+
"nodejs",
11+
"express",
12+
"sequelize",
13+
"rest",
14+
"api",
15+
"postgresql"
16+
],
17+
"author": "bezkoder",
18+
"license": "ISC",
19+
"dependencies": {
20+
"body-parser": "^1.19.0",
21+
"cors": "^2.8.5",
22+
"express": "^4.17.1",
23+
"pg": "^7.17.1",
24+
"pg-hstore": "^2.3.3",
25+
"sequelize": "^5.21.3"
26+
}
27+
}

0 commit comments

Comments
 (0)