+3

Xây dựng api đơn giản với Express, Graphql và Mongodb

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><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ề Mutationsauthentication trong graphql. link repo: https://github.com/haiha210/express-graphql-swagger


All rights reserved

Viblo
Hãy đăng ký một tài khoản Viblo để nhận được nhiều bài viết thú vị hơn.
Đăng kí