Tạo Restfull API - CRUD đơn giản với NodeJS, GraphQL
Bài đăng này đã không được cập nhật trong 4 năm
Chào mọi người,
Nối tiếp quá trình giới thiệu và nghiên cứu về GraphQL, hôm nay mình muốn làm 1 project nhỏ để học tập cũng như hướng dẫn cho mọi người về cách xây dựng ứng dụng sử dụng GraphQL và truy vấn như thế nào.
Nào cùng bắt đầu nhé!
I. GraphQL là gì?
GraphQL là một Graph Query Language được dành cho API. Nó được phát triển bởi Facebook và hiện tại nó được duy trì bởi rất nhiều công ty lớn, và mọi cá nhân trên khắp thế giới.
GraphQL hiện tại thường được dùng cho những dự án lớn thay thế cho REST bởi sự hiệu quả, mạnh mẽ và linh hoạt hơn rất nhiều.
Mọi người có thể tham khảo tại trang chủ của GraphQL: https://graphql.org/
II. Chuẩn bị
Với project mình sẽ demo ở đây, mình sẽ code trên NodeJS 12.
Giả định: Máy bạn đã cài đặt NodeJS và MySQL
2.1. Tạo file package.json
package.json
là 1 file cung cấp thông tin cần thiết cho npm, cho phép nó xác định các thự viện dùng cho dự án cũng như xử lý các phụ thuộc của dự án.
File package.json
:
{
"name": "grapql-crud",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"start": "node app.js"
},
"keywords": [],
"author": "",
"license": "ISC",
"dependencies": {
"apollo-server-express": "^2.17.0",
"dotenv": "^8.2.0",
"express": "^4.17.1",
"mysql2": "^2.2.5",
"sequelize": "^6.3.5"
}
}
Trên đây mình đã thêm các thư viện:
apollo-server-express
: Trình khởi tạo server sidedotenv
: Quản lý các biến môi trường (ENV)express
: Là một khung ứng dụng web cho Node.jsmysql2
: Thư viện MySQL2sequelize
: Đây là 1 trình điều khiển dùng để truy vấn cơ sở dữ liệu
Sau đó, chạy lệnh sau để tiến hành cài đặt các thư viện:
npm i
Bạn sẽ thấy 1 thư mục node_modules được sinh ra, như vậy đã cài đặt xong thư viện.
2.2 Tạo cơ sở dữ liệu sử dụng Mysql
CREATE DATABASE nodejs_api;
CREATE TABLE `products` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(255) DEFAULT NULL,
`color` varchar(255) DEFAULT NULL,
`price` varchar(255) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=latin1;
INSERT INTO `products` VALUES ('1', 'Iphone X', 'Black', '30000000');
INSERT INTO `products` VALUES ('2', 'Samsung S9', 'White', '24000000');
INSERT INTO `products` VALUES ('3', 'Oppo F5', 'Red', '7000000');
Và đây là bảng sau khi chạy sql:
2.3 Tạo file kết nối Database
Trước tiên mình cần đưa các config cho database ra file .env
Đây là file .env
với nội dung:
DB_HOST="localhost"
DB_USER="root"
DB_PASS="root"
DB_NAME="nodejs_api
** Lưu ý: ** Các bạn có thể tạo file .env.example để đưa lên git và đưa file .env
vào .gitignore
Tiếp đến mình sẽ tạo file database.js
:
'use strict';
const Sequelize = require('sequelize')
var db = {}
const sequelize = new Sequelize(
process.env.DB_NAME,
process.env.DB_USER,
process.env.DB_PASS,
{
host: process.env.DB_HOST,
port: process.env.DB_PORT,
dialect: 'mysql',
define: {
freezeTableName: true,
},
pool: {
max: 5,
min: 0,
acquire: 30000,
idle: 10000,
},
operatorsAliases: false,
})
let models = [
require('./models/products.js')
]
// Khởi tạo models
models.forEach(model => {
const seqModel = model(sequelize, Sequelize)
db[seqModel.name] = seqModel
})
// Apply associations
Object.keys(db).forEach(key => {
if ('associate' in db[key]) {
db[key].associate(db)
}
})
db.sequelize = sequelize
module.exports = db
Trong file database.js này mình sử dụng sequelize
để tạo và quản lý database. Để tìm hiểu rõ hơn, các bạn có thể vào trang chủ của sequelize
tại: https://sequelize.org/master/manual/getting-started.html
Như vậy là xong phần config database, khi sử dụng bạn chỉ cần require file database.js
vào là có 1 đối tượng db để truy vấn database rồi.
III. Xây dựng ứng dụng
3.1 Tạo models
Thư mục models này sẽ chứa các models để query DB
Models products:
File models/products.js
:
module.exports = function(sequelize, DataTypes) {
return sequelize.define('products', {
id: {
type: DataTypes.INTEGER(11).UNSIGNED,
allowNull: false,
primaryKey: true,
autoIncrement: true
},
name: {
type: DataTypes.STRING(256),
allowNull: false
},
color: {
type: DataTypes.STRING(256),
allowNull: false
},
price: {
type: DataTypes.STRING(256),
allowNull: false
}
}, {
tableName: 'products',
timestamps: false
});
};
3.2 Tạo GraphQL
Với GraphQL, để tạo được ứng dụng CRUD, chúng ta cần phải tạo 2 mục: Query (dùng để get data) và Mutation (dùng để update, create, delete data).
Tại thư mục root của dự án, tạo file GraphQL/products.js
:
const { gql } = require('apollo-server-express');
const db = require('./../database');
const typeDefs = gql`
type Query {
products: [Product]
product(id: ID!): Product
}
type Product {
id: ID!
name: String!
color: String!
price: String!
}
type Mutation {
updateProduct(
id: Int,
name: String,
color: String,
price: String
): String
createProduct(
name: String,
color: String,
price: String
): String
deletProduct(id: Int): Boolean
}
`
const resolvers = {
Query: {
products: async () => db.products.findAll(),
product: async (obj, args, context, info) =>
db.products.findByPk(args.id),
},
Mutation: {
createProduct: async (root,args,context,info) => {
product = await db.products.create({
name: args.name,
color: args.color,
price: args.price,
});
return product.id;
},
updateProduct: async (root,args,context,info) => {
if (!args.id) return;
product = await db.products.update({
name: args.name,
color: args.color,
price: args.price,
}, {
where: { id: args.id}
});
return 'Update Success!';
},
deleteProduct: async (root,args,context,info) => {
if (!args.id) return;
product = await db.products.destroy({where: {
id: args.id
}})
return 'Delete success!';
}
}
}
module.exports = { typeDefs, resolvers }
Trong file products.js ở trên, có 2 mục mình cần quan tâm đó là:
typeDefs
: Dùng để khai báo các thuộc tính dùng để queryresolvers
: Dùng để khai báo Query, Mutation thao tác với cơ sở dữ liệu.
Sau đó export 2 biến typeDefs
, resolvers
bằng dòng để file khác sử dụng:
module.exports = { typeDefs, resolvers }
Code của GraphQL cũng khá dễ hiểu, các bạn có thể đọc và hiểu luôn. Ngoài ra nên tham khảo cách query DB với sequelize
tại https://sequelize.org/master/manual/getting-started.html
3.3 Tạo server run APP
Tiếp đến, mình sẽ tạo 1 file app.js để run tạo server với nội dung:
//app.js
const express = require('express');
require('dotenv').config({path:'.env'});
const { ApolloServer } = require('apollo-server-express');
//Create server with ApolloServer
const server = new ApolloServer({
modules: [
require('./GraphQL/products'),
]
});
const app = express();
server.applyMiddleware({ app });
//Handle URL not found
app.use(function(req, res) {
res.status(404).send({url: req.originalUrl + ' not found'})
})
//Start APP on Port 4000
app.listen({ port: 4000 }, () => console.log(`🚀 Server ready at http://localhost:4000/graphql`));
Trong file này, chỉ đơn giản mình dùng các thư viện express
, dotenv
, apollo-server-express
để xử lý tạo và quản lý server.
3.4 Review cấu trúc thư mục
Sau 1 hồi thì mình đã có được 1 thư mục như này:
Okey, Giờ đến phần testing.
IV. Testing API
4.1. Get All Products
Request:
{
products {
id,
name,
color,
price
}
}
Response:
4.2. Get Product Detail
Request:
{
product(id: 2){
name,
color,
price
}
}
Response:
4.3. Create Product
Request
mutation {
createProduct(
name: "iPhone 11",
color: "Black",
price: "14000000",
)
}
Response:
4.4. Update Product
Request
mutation {
updateProduct(
id: 1,
name: "iPhone X",
color: "White",
price: "20000000",
)
}
Response:
4.5. Delete Product
mutation {
deleteProduct(
id: 1
)
}
Response:
V. Tài liệu tham khảo
- https://graphql.org/
- https://sequelize.org/master/manual/getters-setters-virtuals.html#combining-getters-and-setters
- https://graphql.org/graphql-js/mutations-and-input-types/
- https://blog.logrocket.com/from-rest-to-graphql/
- https://www.digitalocean.com/community/tutorials/how-to-set-up-a-graphql-server-in-node-js-with-apollo-server-and-sequelize
VI. Kết luận
Như vậy mình đã hướng dẫn và demo cho các bạn cách tạo Restfull API - CRUD với GraphQL
, hy vọng sau bài này các bạn cũng có thể tự tạo được project cho riêng mình sử dụng GraphQL
.
Hẹn gặp mọi người tại bài viết sau
All rights reserved