Xây dựng api đơn giản với Express, Graphql và Mongodb
Bài đăng này đã không được cập nhật trong 5 năm
1. Khởi tạo project
Phiên bản nodejs mình sử dụng là nodejs v8.12.0
, máy mình hiện tại đang sử dụng bản 16.04 nên mình sẽ hương dẫn chi tiết cài cho hệ điều hành này dưới đây, còn
các bạn sử dụng hệ điều hành có thể cài đặt nodejs thông qua nodejs thông qua trang chủ Nodejs.
curl -sL https://deb.nodesource.com/setup_8.x | sudo -E bash -
sudo apt-get update
sudo apt-get install nodejs
Cài đặt yarn
sudo npm install yarn -g
Tiếp theo là tạo project
mkdir express-graphql-app
yarn init -y
Đầu tiên chúng ta cài đặt một vài thư viện:
yarn add apollo-server-express graphql express http-errors mongoose dotenv graphql-tool lodash
yarn add -D babel-cli babel-preset-env babel-preset-stage-2 nodemon
Ý nghĩa của các thư viện này mình sẽ nói ở phần sau của bài viết.
2. Cấu hình babel.
Vì trong bài viết này mình dùng vài chức năng của ES6 nên cần babel
để chuyển đổi ES6 về ES5 để nodejs
có thể hiêu được. Mà ES5 với ES6 là gì vậy? Cơ bản thì ES6 hay ES5 là chữ viết tắt của ECMAScript 6 và ECMAScript 5, là 2 phiên bản khác nhau của ECMAScript - một ngôn ngữ đặc tả do hiệp hội các nhà sản xuất máy tính Châu Âu đề xuất làm tiêu chuẩn của ngôn ngữ Javascript. ES5 được chính thức được ra đời từ năm 2011 do vấy đa số mọi Browser đều hỗ trợ, nhưng ES6 ra mắt từ năm 2015 lại có nhiều tính năng hay ho để lập trình, nên cần babel
một thư viện giúp chúng ta chuyển đổi ES6 về ES5 để nodejs
có thể thực thi được.
Tạo file
.babelrc
{
"presets": ["env", "stage-2"]
}
thêm vào file package.json
"scripts": {
"start": "nodemon --exec babel-node ./index.js"
},
Tạo file inde.js
import express from 'express';
const app = express;
const PORT = progress.env.PORT || 3000;
app.listen(PORT, () => {
console.log(`server run in port ${PORT}`);
})
dùng lệnh yarn start
để khởi chạy server
Sử dụng thư viện dotenv
để ứng dụng của chúng ta đọc được file .env
. Thêm vào file index.js
import dotenv from 'dotenv'
dotenv.config()
3. Kết nối với mongodb của Mlab
Mlab là database mongodb trực tuyến phổ biến trên thế giới, nó cung cấp các gói sử dụng dung lượng thấp nhưng hoàn toàn miễn phí nên rất nhiều sử dụng để nguyên cứu về mongodb. Chúng ta dễ dàng đăng ký một tài khoản của mlab. Khi đăng kí thành công chúng ta tiến hành tạo mới database và có kết nối với database thông qua một connect string
như dưới hình, với <dbuser>
và <dbpassword>
là thông tin tài khoản tạo ở tab USER
.
Sau đó tiến hành kết nối với database thông qua connect string
tại file index.js
. Ở đây ta dùng thư viện mongoose để kết nối database.
import mongoose from 'mongoose';
mongoose.Promise = global.Promise;
mongoose.connect(process.env.LINK_MONGODB, {useNewUrlParser: true});
Tiến hành lưu connect string
vào file .env
mongodb://<dbuser>:<dbpassword>@ds161653.mlab.com:61653/express-graphql
Tiếp đến là tạo model mongoose, models/todo.js
import mongoose, { Schema } from 'mongoose';
import timestamps from 'mongoose-timestamp';
mongoose.Promise = global.Promise;
const TodoSchema = new Schema({
_id: {
type: String
},
text: {
type: String,
required: true
},
idComplete: {
type: Boolean,
default: false
}
});
TodoSchema.plugin(timestamps);
const Todo = mongoose.model('Todo', TodoSchema, 'todos');
export default Todo;
tạo file models/index.js
để đễ dàng truy xuất đến model.
import Todo from './todo';
export {
Todo
}
4. Query
Khởi tạo schema, query và resolers cho getTodo()
Graphql graphql/todo/index.js
import TodoService from './services';
export const queries = [
`
#get all todo
getTodo: [Todo]
`
]
export const schema = [
`
type Todo {
_id: String
text: String
idComplete: Boolean
}
`
]
export const resolers = {
Query: {
getTodo(parent, args, context) {
return TodoService.getTodo();
}
}
}
Tạo file graphql/todo/service.js
để thực thi việc get data từ database
import { Todo } from '../../models';
import handleError from '../../util/handleError';
async function getTodo() {
try {
return await Todo.find();
} catch(error) {
handleError(500);
}
}
export default {
getTodo
}
Hàm xử lý lỗi theo status util/handleError.js
import createError from 'http-errors';
export default function handleError(statusCode) {
const error = new createError(statusCode)
error.statusCode = statusCode;
throw error;
}
cuối cùng index.js
là khai báo đối tượng ApolloServer, và kết nối với express
import { ApolloServer } from 'apollo-server-express';
import schema from './graphql';
...
const server = new ApolloServer({schema,
context: ({req,res}) => ({
provider: req,
headers: req.headers
}),
formatError: ({extensions}) => {
const {message, statusCode} = extensions.exception;
return {
message,
statusCode,
}
}
});
const app = express();
server.applyMiddleware({ app });
Giao diện của graphqlui của chung ta ở localhost:3000/graphql
Tiến hành tạo một query getTodo, ở đây kết quả trả về là một mảng rỗng vì do chưa thêm dữ liệu
Ta có thể tạo dữ liệu thông qua mlab, bằng việc insert một document vào trong database dưới dạng như sau
Bài viết cũng đã khá dài rồi mình xin dùng ở đây, cảm ơn các bạn đã theo dõi hết bài viết. Phần sau mình sẽ tiếp tục là tiếp về Mutations
và authentication
trong graphql.
link repo: https://github.com/haiha210/express-graphql-swagger
All rights reserved