Cách xây dựng và triển khai server GraphQL với Node.js và MongoDB trên Ubuntu 18.04
GraphQL được Facebook phát hành công khai vào năm 2015 dưới dạng ngôn ngữ truy vấn cho các API giúp dễ dàng truy vấn và thay đổi dữ liệu từ các bộ sưu tập dữ liệu khác nhau. Từ một điểm cuối duy nhất, bạn có thể truy vấn và thay đổi nhiều nguồn dữ liệu với một yêu cầu ĐĂNG. GraphQL giải quyết một số lỗi thiết kế phổ biến trong kiến trúc API REST, chẳng hạn như các tình huống mà điểm cuối trả về nhiều thông tin hơn bạn thực sự cần. Ngoài ra, có thể khi sử dụng REST API, bạn cần gửi yêu cầu đến nhiều điểm cuối REST để thu thập tất cả thông tin bạn yêu cầu — một tình huống được gọi là vấn đề n + 1. Một ví dụ về điều này sẽ là khi bạn muốn hiển thị thông tin của user , nhưng cần thu thập dữ liệu như chi tiết cá nhân và địa chỉ từ các điểm cuối khác nhau.Những vấn đề này không áp dụng cho GraphQL vì nó chỉ có một điểm cuối, có thể trả về dữ liệu từ nhiều bộ sưu tập. Dữ liệu nó trả về phụ thuộc vào truy vấn mà bạn gửi đến điểm cuối này. Trong truy vấn này, bạn xác định cấu trúc của dữ liệu bạn muốn nhận, bao gồm bất kỳ bộ sưu tập dữ liệu lồng nhau nào. Ngoài truy vấn, bạn cũng có thể sử dụng đột biến để thay đổi dữ liệu trên server GraphQL và đăng ký để theo dõi các thay đổi trong dữ liệu. Để biết thêm thông tin về GraphQL và các khái niệm của nó, bạn có thể truy cập tài liệu trên trang web chính thức.
Vì GraphQL là một ngôn ngữ truy vấn có rất nhiều tính linh hoạt, nó kết hợp đặc biệt tốt với database dựa trên tài liệu như MongoDB . Cả hai công nghệ đều dựa trên các schemas phân cấp, được định kiểu và phổ biến trong cộng đồng JavaScript. Ngoài ra, dữ liệu của MongoDB được lưu trữ dưới dạng các đối tượng JSON, vì vậy không cần phân tích cú pháp bổ sung trên server GraphQL.
Trong hướng dẫn này, bạn sẽ xây dựng và triển khai server GraphQL với Node.js có thể truy vấn và thay đổi dữ liệu từ database MongoDB đang chạy trên Ubuntu 18.04. Vào cuối hướng dẫn này, bạn có thể truy cập dữ liệu trong database của bạn bằng cách sử dụng một điểm cuối duy nhất, bằng cách gửi yêu cầu đến server trực tiếp thông qua terminal và bằng cách sử dụng giao diện playground GraphiQL được tạo sẵn. Với playground này, bạn có thể khám phá nội dung của server GraphQL bằng cách gửi các truy vấn, đột biến và đăng ký. Ngoài ra, bạn có thể tìm thấy các bản trình bày trực quan của các schemas được xác định cho server này.
Ở cuối hướng dẫn này, bạn sẽ sử dụng playground GraphiQL để giao tiếp nhanh với server GraphQL của bạn :
Yêu cầu
Trước khi bắt đầu hướng dẫn này, bạn cần những thứ sau:
- Server Ubuntu 18.04 được cài đặt theo hướng dẫn cài đặt server ban đầu Ubuntu 18.04 , bao gồm user không phải root có quyền sudo và firewall . 
- Cài đặt MongoDB chạy trên Ubuntu 18.04, bạn có thể cài đặt theo hướng dẫn của ta Cách cài đặt MongoDB trên Ubuntu 18.04 . 
- Đã cài đặt Nginx, như đã thấy trong Cách cài đặt Nginx trên Ubuntu 18.04 , bao gồm Bước 4 - Cài đặt khối server . 
- Để cho phép truy cập từ xa vào server GraphQL của bạn, bạn cần một tên domain đủ điều kiện (FQDN) và một bản ghi A trỏ tới IP server của bạn. Bạn có thể tìm hiểu thêm về điều này bằng cách đọc qua Giới thiệu về Thuật ngữ, Thành phần và Khái niệm DNS hoặc Tài liệu về Miền và DNS nếu bạn có account DigitalOcean. 
- Làm quen với JavaScript mà bạn có thể có được từ loạt bài Cách viết mã trong JavaScript . 
Bước 1 - Cài đặt database MongoDB
Trước khi tạo server GraphQL, hãy đảm bảo database của bạn được cấu hình đúng, đã cài đặt xác thực và chứa đầy dữ liệu mẫu. Đối với điều này, bạn cần kết nối với server Ubuntu 18.04 chạy database MongoDB từ dấu nhắc lệnh của bạn. Tất cả các bước trong hướng dẫn này sẽ diễn ra trên server này.
Sau khi bạn đã cài đặt kết nối, hãy chạy lệnh sau để kiểm tra xem MongoDB có đang đang chạy trên server của bạn hay không:
- sudo systemctl status mongodb 
Bạn sẽ thấy kết quả sau trong terminal của bạn , cho biết database MongoDB đang hoạt động:
Output● mongodb.service - An object/document-oriented database    Loaded: loaded (/lib/systemd/system/mongodb.service; enabled; vendor preset: enabled)    Active: active (running) since Sat 2019-02-23 12:23:03 UTC; 1 months 13 days ago      Docs: man:mongod(1)  Main PID: 2388 (mongod)     Tasks: 25 (limit: 1152)    CGroup: /system.slice/mongodb.service            └─2388 /usr/bin/mongod --unixSocketPrefix=/run/mongodb --config /etc/mongodb.conf Trước khi tạo database nơi bạn sẽ lưu trữ dữ liệu mẫu, trước tiên bạn cần tạo một user administrator , vì những regular user có phạm vi đến một database cụ thể. Bạn có thể thực hiện việc này bằng cách chạy lệnh sau để mở shell MongoDB:
- mongo 
Với MongoDB shell, bạn sẽ có quyền truy cập trực tiếp vào database MongoDB và có thể tạo user hoặc database và truy vấn dữ liệu. Bên trong shell này, thực hiện lệnh sau sẽ thêm user quản trị mới vào MongoDB. Bạn có thể thay thế các từ khóa được đánh dấu bằng tổ hợp tên user và password của riêng mình, nhưng đừng quên ghi chúng vào đâu đó.
- use admin 
- db.createUser({ 
-     user: "admin_username", 
-     pwd: "admin_password", 
-     roles: [{ role: "root", db: "admin"}] 
- }) 
Dòng đầu tiên của lệnh trước đó chọn database  được gọi là admin , đây là database  nơi lưu trữ tất cả các  role   administrator . Với phương thức db.createUser() bạn có thể tạo  user  thực và xác định tên  user , password  và  role  của nó.
Thực hiện lệnh này sẽ trả về:
OutputSuccessfully added user: {     "user" : "admin_username",     "roles" : [         {             "role" : "root",             "db" : "admin"         }     ] }  Đến đây bạn  có thể đóng  shell  MongoDB  bằng lệnh  exit .
Tiếp theo, đăng nhập lại MongoDB shell, nhưng lần này với user quản trị mới được tạo:
- mongo -u "admin_username" -p "admin_password" --authenticationDatabase "admin" 
Lệnh này sẽ mở  shell  MongoDB  với quyền  là một  user  cụ thể, trong đó cờ -u chỉ định tên  user  và cờ -p là password  của  user  đó. Cờ bổ sung --authenticationDatabase chỉ định rằng bạn muốn đăng nhập  với quyền   administrator  .
 Tiếp theo, bạn sẽ chuyển sang database  mới và sau đó sử dụng phương thức db.createUser() để tạo  user  mới có quyền thực hiện thay đổi đối với database  này. Thay thế các phần được đánh dấu bằng thông tin  của bạn , đảm bảo ghi các thông tin đăng nhập này xuống.
Chạy lệnh sau trong shell MongoDB:
- use database_name 
- db.createUser({ 
-     user: "username", 
-     pwd: "password", 
-     roles: ["readWrite"] 
- }) 
Kết quả sẽ trả về như sau:
OutputSuccessfully added user: { "user" : "username", "roles" : ["readWrite"] } Sau khi tạo database  và  user , hãy điền vào database  này với dữ liệu mẫu có thể được  server  GraphQL truy vấn sau này trong hướng dẫn này. Đối với điều này, bạn có thể sử dụng mẫu bộ sưu tập bios từ trang web MongoDB. Bằng cách thực hiện các lệnh trong đoạn mã sau, bạn sẽ chèn một version  nhỏ hơn của tập dữ liệu thu thập bios này vào database   của bạn . Bạn có thể thay thế các phần đánh dấu bằng thông tin riêng của bạn, nhưng đối với mục đích của hướng dẫn này, đặt tên cho bộ sưu tập bios :
- db.bios.insertMany([ 
-    { 
-        "_id" : 1, 
-        "name" : { 
-            "first" : "John", 
-            "last" : "Backus" 
-        }, 
-        "birth" : ISODate("1924-12-03T05:00:00Z"), 
-        "death" : ISODate("2007-03-17T04:00:00Z"), 
-        "contribs" : [ 
-            "Fortran", 
-            "ALGOL", 
-            "Backus-Naur Form", 
-            "FP" 
-        ], 
-        "awards" : [ 
-            { 
-                "award" : "W.W. McDowell Award", 
-                "year" : 1967, 
-                "by" : "IEEE Computer Society" 
-            }, 
-            { 
-                "award" : "National Medal of Science", 
-                "year" : 1975, 
-                "by" : "National Science Foundation" 
-            }, 
-            { 
-                "award" : "Turing Award", 
-                "year" : 1977, 
-                "by" : "ACM" 
-            }, 
-            { 
-                "award" : "Draper Prize", 
-                "year" : 1993, 
-                "by" : "National Academy of Engineering" 
-            } 
-        ] 
-    }, 
-    { 
-        "_id" : ObjectId("51df07b094c6acd67e492f41"), 
-        "name" : { 
-            "first" : "John", 
-            "last" : "McCarthy" 
-        }, 
-        "birth" : ISODate("1927-09-04T04:00:00Z"), 
-        "death" : ISODate("2011-12-24T05:00:00Z"), 
-        "contribs" : [ 
-            "Lisp", 
-            "Artificial Intelligence", 
-            "ALGOL" 
-        ], 
-        "awards" : [ 
-            { 
-                "award" : "Turing Award", 
-                "year" : 1971, 
-                "by" : "ACM" 
-            }, 
-            { 
-                "award" : "Kyoto Prize", 
-                "year" : 1988, 
-                "by" : "Inamori Foundation" 
-            }, 
-            { 
-                "award" : "National Medal of Science", 
-                "year" : 1990, 
-                "by" : "National Science Foundation" 
-            } 
-        ] 
-    } 
- ]); 
Khối mã này là một mảng bao gồm nhiều đối tượng chứa thông tin về các nhà khoa học thành công trong quá khứ. Sau khi chạy các lệnh này để nhập bộ sưu tập này vào database của bạn, bạn sẽ nhận được thông báo sau cho biết dữ liệu đã được thêm vào:
Output{     "acknowledged" : true,     "insertedIds" : [         1,         ObjectId("51df07b094c6acd67e492f41")     ] } Sau khi thấy thông báo thành công, bạn có thể đóng  shell  MongoDB  bằng lệnh  exit . Tiếp theo, hãy  cấu hình  cài đặt MongoDB để kích hoạt ủy quyền để chỉ những  user  được xác thực mới có thể truy cập dữ liệu. Để chỉnh sửa cấu hình cài đặt MongoDB, hãy mở file  chứa cài đặt cho cài đặt này:
- sudo nano /etc/mongodb.conf 
Bỏ comment được đánh dấu trong mã sau để bật ủy quyền:
... # Turn on/off security.  Off is currently the default #noauth = true auth = true ... Để làm cho những thay đổi này hoạt động, hãy khởi động lại MongoDB bằng lệnh:
- sudo systemctl restart mongodb 
Đảm bảo rằng database đang chạy lại bằng cách chạy lệnh :
- sudo systemctl status mongodb 
Điều này sẽ mang lại kết quả tương tự như sau:
Output● mongodb.service - An object/document-oriented database    Loaded: loaded (/lib/systemd/system/mongodb.service; enabled; vendor preset: enabled)    Active: active (running) since Sat 2019-02-23 12:23:03 UTC; 1 months 13 days ago      Docs: man:mongod(1)  Main PID: 2388 (mongod)     Tasks: 25 (limit: 1152)    CGroup: /system.slice/mongodb.service            └─2388 /usr/bin/mongod --unixSocketPrefix=/run/mongodb --config /etc/mongodb.conf Để đảm bảo user của bạn có thể kết nối với database bạn vừa tạo, hãy thử mở shell MongoDB với quyền là user đã xác thực bằng lệnh:
- mongo -u "username" -p "password" --authenticationDatabase "database_name" 
Thao tác này sử dụng các cờ tương tự như trước, chỉ lần này --authenticationDatabase được đặt thành database  bạn đã tạo và điền vào dữ liệu mẫu.
Đến đây bạn đã thêm thành công một user quản trị và một user khác có quyền truy cập đọc / ghi vào database với dữ liệu mẫu. Ngoài ra, database đã kích hoạt ủy quyền nghĩa là bạn cần có tên user và password để truy cập nó. Trong bước tiếp theo, bạn sẽ tạo server GraphQL sẽ được kết nối với database này sau trong hướng dẫn.
Bước 2 - Tạo Server GraphQL
 Với database  được  cấu hình  và chứa đầy dữ liệu mẫu, đã đến lúc tạo một  server  GraphQL có thể truy vấn và thay đổi dữ liệu này. Đối với điều này, bạn sẽ sử dụng Express và express-graphql , cả hai đều chạy trên Node.js. Express là một khung công tác nhẹ để nhanh chóng tạo các  server  HTTP Node.js và express-graphql cung cấp phần mềm trung gian để có thể nhanh chóng xây dựng các  server  GraphQL.
Bước đầu tiên là đảm bảo máy của bạn được cập nhật:
- sudo apt update 
Tiếp theo, cài đặt Node.js trên server của bạn bằng cách chạy các lệnh sau. Cùng với Node.js, bạn cũng sẽ cài đặt npm , một trình quản lý gói cho JavaScript chạy trên Node.js.
- sudo apt install nodejs npm 
Sau khi thực hiện theo quy trình cài đặt, hãy kiểm tra xem version  Node.js bạn vừa cài đặt có phải là v8.10.0 trở lên hay không:
- node -v 
Kết quả sẽ trả về như sau:
Outputv8.10.0 Để khởi tạo một dự án JavaScript mới, hãy chạy các lệnh sau trên  server   với quyền  là  user  sudo và thay thế các từ khóa được đánh dấu bằng tên cho dự án của bạn.
Trước tiên, hãy chuyển vào folder root của server của bạn:
- cd 
Khi đó, hãy tạo một folder mới có tên theo dự án của bạn:
- mkdir project_name 
Di chuyển vào folder này:
- cd project_name  
Cuối cùng, khởi tạo một gói npm mới bằng lệnh sau:
- sudo npm init -y 
Sau khi chạy npm init -y bạn sẽ nhận được thông báo thành công rằng file  package.json sau đã được tạo:
OutputWrote to /home/username/project_name/package.json:  {   "name": "project_name",   "version": "1.0.0",   "description": "",   "main": "index.js",   "scripts": {     "test": "echo \"Error: no test specified\" && exit 1"   },   "keywords": [],   "author": "",   "license": "ISC" } Lưu ý: Bạn cũng có thể thực thi npm init mà không có cờ -y , sau đó bạn sẽ trả lời nhiều câu hỏi để  cài đặt  tên dự án, tác giả, v.v. Bạn có thể nhập chi tiết hoặc chỉ cần nhấn enter để tiếp tục.
Đến đây bạn đã khởi tạo dự án, hãy cài đặt các gói bạn cần để cài đặt server GraphQL:
- sudo npm install --save express express-graphql graphql 
Tạo một file  mới có tên là index.js và sau đó mở file  này  bằng lệnh: 
- sudo nano index.js 
Tiếp theo, thêm khối mã sau vào file mới tạo để cài đặt server GraphQL:
const express = require('express'); const graphqlHTTP = require('express-graphql'); const { buildSchema } = require('graphql');  // Construct a schema, using GraphQL schema language const schema = buildSchema(`   type Query {     hello: String   } `);  // Provide resolver functions for your schema fields const resolvers = {   hello: () => 'Hello world!' };  const app = express(); app.use('/graphql', graphqlHTTP({   schema,   rootValue: resolvers })); app.listen(4000);  console.log(`🚀 Server ready at http://localhost:4000/graphql`); Khối mã này bao gồm một số phần đều quan trọng. Đầu tiên, bạn mô tả schemas của dữ liệu được trả về bởi API GraphQL:
... // Construct a schema, using GraphQL schema language const schema = buildSchema(`   type Query {     hello: String   } `); ... Kiểu Query xác định những truy vấn nào có thể được thực thi và nó sẽ trả về kết quả ở định dạng nào.  Như bạn thấy , truy vấn duy nhất được xác định là hello trả về dữ liệu ở định dạng String .
Phần tiếp theo cài đặt các trình phân giải , nơi dữ liệu được trùng với các schemas mà bạn có thể truy vấn:
... // Provide resolver functions for your schema fields const resolvers = {   hello: () => 'Hello world!' }; ... Các trình phân giải này được liên kết trực tiếp với các schemas và trả về dữ liệu trùng với các schemas này.
Phần cuối cùng của khối mã này khởi tạo server GraphQL, tạo điểm cuối API với Express và mô tả cổng mà điểm cuối GraphQL đang chạy:
... const app = express(); app.use('/graphql', graphqlHTTP({   schema,   rootValue: resolvers })); app.listen(4000);  console.log(`🚀 Server ready at http://localhost:4000/graphql`); Sau khi bạn đã thêm những dòng này, hãy lưu và thoát khỏi index.js .
 Tiếp theo, để thực sự chạy  server  GraphQL, bạn cần chạy file  index.js với Node.js. Điều này có thể được thực hiện theo cách thủ công từ dòng lệnh, nhưng thông thường bạn nên  cài đặt  file  package.json để thực hiện việc này cho bạn.
 Mở file  package.json :
- sudo nano package.json 
Thêm dòng được đánh dấu sau vào file này:
{   "name": "project_name",   "version": "1.0.0",   "description": "",   "main": "index.js",   "scripts": {     "start": "node index.js",     "test": "echo \"Error: no test specified\" && exit 1"   },   "keywords": [],   "author": "",   "license": "ISC" } Lưu và thoát khỏi file .
Để khởi động server GraphQL, hãy thực hiện lệnh sau trong terminal:
- npm start 
Khi bạn chạy điều này, dấu nhắc terminal sẽ không xuất hiện và một thông báo sẽ xuất hiện để xác nhận server GraphQL đang chạy:
Output🚀 Server ready at http://localhost:4000/graphql Nếu bây giờ bạn mở một phiên  terminal  khác, bạn có thể kiểm tra xem  server  GraphQL có đang chạy hay không  bằng cách chạy lệnh  sau. Thao tác này sẽ gửi một yêu cầu curl POST với phần thân JSON sau cờ --data chứa truy vấn GraphQL của bạn tới điểm cuối local :
- curl -X POST -H "Content-Type: application/json" --data '{ "query": "{ hello }" }' http://localhost:4000/graphql 
Điều này sẽ thực thi truy vấn như được mô tả trong schemas GraphQL trong mã của bạn và trả về dữ liệu ở định dạng JSON có thể dự đoán được, bằng với dữ liệu khi được trả về trong trình phân giải:
Output{ "data": { "hello": "Hello world!" } } Lưu ý: Trong trường hợp  server  Express gặp sự cố hoặc bị kẹt, bạn cần phải tự node tiến trình node đang chạy trên  server . Để giết tất cả các quy trình như vậy, bạn có thể thực hiện như sau:
- killall node 
Sau đó, bạn có thể khởi động lại server GraphQL bằng lệnh:
- npm start 
Trong bước này, bạn đã tạo version đầu tiên của server GraphQL hiện đang chạy trên một điểm cuối local có thể được truy cập trên server của bạn. Tiếp theo, bạn sẽ kết nối các trình phân giải của bạn với database MongoDB.
Bước 3 - Kết nối với Database MongoDB
Với server GraphQL, bây giờ bạn có thể cài đặt kết nối với database MongoDB mà bạn đã cấu hình và điền dữ liệu trước đó và tạo một schemas mới phù hợp với dữ liệu này.
Để có thể kết nối với MongoDB từ server GraphQL, hãy cài đặt gói JavaScript cho MongoDB từ npm:
- sudo npm install --save mongodb 
Khi cái này đã được cài đặt, hãy mở index.js trong editor  của bạn:
- sudo nano index.js 
Tiếp theo, thêm mã được đánh dấu sau vào index.js ngay sau các phần phụ thuộc đã nhập và điền các giá trị được đánh dấu bằng chi tiết kết nối  của bạn  vào database  MongoDB local . username , password và database_name là những tên bạn đã tạo trong bước đầu tiên của hướng dẫn này.
const express = require('express'); const graphqlHTTP = require('express-graphql'); const { buildSchema } = require('graphql'); const { MongoClient } = require('mongodb');  const context = () => MongoClient.connect('mongodb://username:password@localhost:27017/database_name', { useNewUrlParser: true }).then(client => client.db('database_name')); ... Các dòng này thêm kết nối đến database MongoDB local vào một hàm được gọi là ngữ cảnh . Chức năng ngữ cảnh này sẽ có sẵn cho mọi trình phân giải, đó là lý do tại sao bạn sử dụng chức năng này để cài đặt các kết nối database .
 Tiếp theo, trong index.js của bạn, hãy thêm hàm ngữ cảnh vào quá trình khởi tạo  server  GraphQL bằng cách chèn các dòng được đánh dấu sau:
... const app = express(); app.use('/graphql', graphqlHTTP({   schema,   rootValue: resolvers,   context })); app.listen(4000);  console.log(`🚀 Server ready at http://localhost:4000/graphql`);  Đến đây bạn  có thể gọi hàm ngữ cảnh này từ trình phân giải  của bạn  và do đó đọc các biến từ database  MongoDB. Nếu bạn nhìn lại bước đầu tiên của hướng dẫn này, bạn có thể thấy những giá trị nào có trong database . Từ đây, xác định một schemas  GraphQL mới phù hợp với cấu trúc dữ liệu này. Ghi đè giá trị trước đó cho schema hằng số bằng các dòng được đánh dấu sau:
... // Construct a schema, using GrahQL schema language const schema = buildSchema(`   type Query {     bios: [Bio]   }   type Bio {     name: Name,     title: String,     birth: String,     death: String,     awards: [Award]   }   type Name {     first: String,     last: String   },   type Award {     award: String,     year: Float,     by: String   } `); ... Loại Query đã thay đổi và bây giờ trả về một bộ sưu tập Bio loại mới. Loại mới này bao gồm một số loại bao gồm hai loại không vô hướng khác là Name và Awards ,  nghĩa là  các loại này không  trùng với  định dạng  được định nghĩa  như String hoặc Float . Để biết thêm thông tin về cách xác định schemas  GraphQL, bạn có thể xem tài liệu về GraphQL.
 Ngoài ra, vì trình phân giải liên kết dữ liệu từ database  với schemas , hãy cập nhật mã cho trình phân giải khi bạn thực hiện thay đổi đối với schemas . Tạo một trình phân giải mới được gọi là bios , bằng với Query có thể được tìm thấy trong schemas  và tên của tập hợp trong database .  Lưu ý , trong trường hợp này, tên của bộ sưu tập trong db.collection('bios') là bios , nhưng điều này sẽ thay đổi nếu bạn đã chỉ định một tên khác cho bộ sưu tập  của bạn .
 Thêm dòng được đánh dấu sau vào index.js :
... // Provide resolver functions for your schema fields const resolvers = {   bios: (args, context) => context().then(db => db.collection('bios').find().toArray()) }; ... Hàm này sẽ sử dụng hàm ngữ cảnh mà bạn có thể sử dụng để truy xuất các biến từ database  MongoDB. Khi bạn đã thực hiện những thay đổi này đối với mã, hãy lưu và thoát khỏi index.js .
 Để  áp dụng các thay đổi  này hoạt động, bạn cần khởi động lại  server  GraphQL. Bạn có thể dừng quá trình hiện tại bằng cách sử dụng tổ hợp bàn phím CTRL + C và khởi động  server  GraphQL  bằng lệnh: 
- npm start 
 Đến đây bạn  có thể sử dụng schemas  đã cập nhật và truy vấn dữ liệu bên trong database . Nếu bạn nhìn vào schemas , bạn sẽ thấy rằng Query cho bios trả về loại Bio ; kiểu này cũng có thể trả về kiểu Name .
Để trả lại tất cả họ và tên cho tất cả các bios trong database , hãy gửi yêu cầu sau đến server GraphQL trong một cửa sổ terminal mới:
-  curl -X POST -H "Content-Type: application/json" --data '{ "query": "{ bios { name { first, last } } }" }' http://localhost:4000/graphql 
Điều này sẽ trả về một đối tượng JSON phù hợp với cấu trúc của schemas :
Output{"data":{"bios":[{"name":{"first":"John","last":"Backus"}},{"name":{"first":"John","last":"McCarthy"}}]}} Bạn có thể dễ dàng truy xuất nhiều biến hơn từ bios bằng cách mở rộng truy vấn với bất kỳ loại nào được mô tả trong loại cho Bio .
 Ngoài ra, bạn có thể truy xuất tiểu sử bằng cách chỉ định một id . Để thực hiện việc này, bạn cần thêm một loại khác vào Loại Query và mở rộng trình phân giải. Để thực hiện việc này, hãy mở index.js trong editor  của bạn:
- sudo nano index.js 
Thêm các dòng mã được đánh dấu sau:
... // Construct a schema, using GrahQL schema language const schema = buildSchema(`   type Query {     bios: [Bio]     bio(id: Int): Bio   }    ...    // Provide resolver functions for your schema fields   const resolvers = {     bios: (args, context) => context().then(db => db.collection('bios').find().toArray()),     bio: (args, context) => context().then(db => db.collection('bios').findOne({ _id: args.id }))   };   ... Lưu và thoát khỏi file .
 Trong terminal  đang chạy  server  GraphQL của bạn, nhấn CTRL + C để ngừng chạy, sau đó thực hiện các thao tác sau để khởi động lại:
- npm start 
Trong một cửa sổ terminal khác, hãy thực hiện yêu cầu GraphQL sau:
- curl -X POST -H "Content-Type: application/json" --data '{ "query": "{ bio(id: 1) { name { first, last } } }" }' http://localhost:4000/graphql 
Điều này trả về mục nhập cho tiểu sử có id bằng 1 :
Output{ "data": { "bio": { "name": { "first": "John", "last": "Backus" } } } } Có thể truy vấn dữ liệu từ database  không phải là tính năng duy nhất của GraphQL; bạn cũng có thể thay đổi dữ liệu trong database . Để làm điều này, hãy mở index.js :
- sudo nano index.js 
Bên cạnh kiểu Query bạn cũng có thể sử dụng kiểu Mutation , cho phép bạn thay đổi database . Để sử dụng kiểu này, hãy thêm nó vào schemas  và cũng tạo kiểu đầu vào bằng cách chèn các dòng được đánh dấu sau:
... // Construct a schema, using GraphQL schema language const schema = buildSchema(`   type Query {     bios: [Bio]     bio(id: Int): Bio   }   type Mutation {     addBio(input: BioInput) : Bio   }   input BioInput {     name: NameInput     title: String     birth: String     death: String   }   input NameInput {     first: String     last: String   } ... Các kiểu đầu vào này xác định biến nào  được dùng  làm đầu vào, mà bạn có thể truy cập trong trình phân giải và sử dụng để chèn tài liệu mới vào database . Thực hiện việc này bằng cách thêm các dòng sau vào index.js :
... // Provide resolver functions for your schema fields const resolvers = {   bios: (args, context) => context().then(db => db.collection('bios').find().toArray()),   bio: (args, context) => context().then(db => db.collection('bios').findOne({ _id: args.id })),   addBio: (args, context) => context().then(db => db.collection('bios').insertOne({ name: args.input.name, title: args.input.title, death: args.input.death, birth: args.input.birth})).then(response => response.ops[0]) }; ... Cũng như với các trình phân giải cho các truy vấn thông thường, bạn cần trả về một giá trị từ trình phân giải trong index.js . Trong trường hợp Mutation trong đó loại Bio bị đột biến, bạn sẽ trả về giá trị của bio bị đột biến.
  Đến đây,  index.js của bạn sẽ chứa các dòng sau:
iconst express = require('express'); const graphqlHTTP = require('express-graphql'); const { buildSchema } = require('graphql'); const { MongoClient } = require('mongodb');  const context = () => MongoClient.connect('mongodb://username:password@localhost:27017/database_name', { useNewUrlParser: true })   .then(client => client.db('GraphQL_Test'));  // Construct a schema, using GraphQL schema language const schema = buildSchema(`   type Query {     bios: [Bio]     bio(id: Int): Bio   }   type Mutation {     addBio(input: BioInput) : Bio   }   input BioInput {     name: NameInput     title: String     birth: String     death: String   }   input NameInput {     first: String     last: String   }   type Bio {     name: Name,     title: String,     birth: String,     death: String,     awards: [Award]   }   type Name {     first: String,     last: String   },   type Award {     award: String,     year: Float,     by: String   } `);  // Provide resolver functions for your schema fields const resolvers = {   bios: (args, context) =>context().then(db => db.collection('Sample_Data').find().toArray()),   bio: (args, context) =>context().then(db => db.collection('Sample_Data').findOne({ _id: args.id })),   addBio: (args, context) => context().then(db => db.collection('Sample_Data').insertOne({ name: args.input.name, title: args.input.title, death: args.input.death, birth: args.input.birth})).then(response => response.ops[0]) };  const app = express(); app.use('/graphql', graphqlHTTP({   schema,   rootValue: resolvers,   context })); app.listen(4000);  console.log(`🚀 Server ready at http://localhost:4000/graphql`); Lưu và thoát khỏi index.js .
 Để kiểm tra xem đột biến mới của bạn có đang hoạt động hay không, hãy khởi động lại  server  GraphQL bằng cách nhấn CTRL + c và chạy npm start trong terminal  đang chạy  server  GraphQL của bạn, sau đó mở một phiên  terminal  khác để thực hiện yêu cầu curl sau. Cũng giống như yêu cầu curl cho các truy vấn, phần thân trong cờ --data sẽ được gửi đến  server  GraphQL. Các phần được đánh dấu sẽ được thêm vào database :
- curl -X POST -H "Content-Type: application/json" --data '{ "query": "mutation { addBio(input: { name: { first: \"test\", last: \"user\" } }) { name { first, last } } }" }' http://localhost:4000/graphql 
Điều này trả về kết quả sau, nghĩa là bạn vừa chèn một tiểu sử mới vào database :
Output{ "data": { "addBio": { "name": { "first": "test", "last": "user" } } } } Trong bước này, bạn đã tạo kết nối với MongoDB và server GraphQL, cho phép bạn truy xuất và thay đổi dữ liệu từ database này bằng cách thực hiện các truy vấn GraphQL. Tiếp theo, bạn sẽ hiển thị server GraphQL này để truy cập từ xa.
Bước 4 - Cho phép truy cập từ xa
 Sau khi  cài đặt  database  và  server  GraphQL, bây giờ bạn có thể  cấu hình   server  GraphQL để cho phép truy cập từ xa. Đối với điều này, bạn sẽ sử dụng Nginx, mà bạn đã  cài đặt  trong hướng dẫn  yêu cầu  Cách cài đặt Nginx trên Ubuntu 18.04 . Cấu hình Nginx này có thể được tìm thấy trong file  /etc/nginx/sites-available/ example.com , trong đó example.com là tên  server  bạn đã thêm trong hướng dẫn  yêu cầu .
 Mở file  này để chỉnh sửa, thay thế domain  của bạn bằng example.com :
- sudo nano /etc/nginx/sites-available/example.com 
Trong file  này, bạn có thể tìm thấy khối  server  lắng nghe cổng 80 , nơi bạn đã  cài đặt  giá trị cho server_name trong hướng dẫn  yêu cầu . Bên trong khối  server  này, hãy thay đổi giá trị cho root thành folder  mà bạn đã tạo mã cho  server  GraphQL và thêm index.js làm index . Ngoài ra, trong khối vị trí, hãy đặt proxy_pass để bạn có thể sử dụng IP của  server  hoặc domain  tùy chỉnh để tham chiếu đến  server  GraphQL:
server {   listen 80;   listen [::]:80;    root /project_name;   index index.js;    server_name example.com;    location / {     proxy_pass http://localhost:4000/graphql;   } } Đảm bảo không có lỗi cú pháp Nginx trong file cấu hình này bằng lệnh:
- sudo nginx -t 
Bạn sẽ nhận được kết quả sau:
Outputnginx: the configuration file /etc/nginx/nginx.conf syntax is ok nginx: configuration file /etc/nginx/nginx.conf test is successful Khi không tìm thấy lỗi nào cho file cấu hình, hãy khởi động lại Nginx:
- sudo systemctl restart nginx 
Bây giờ,  bạn có thể  truy cập  server  GraphQL  của bạn  từ bất kỳ tab phiên  terminal  nào bằng cách thực thi và thay thế example.com bằng IP của  server  hoặc domain  tùy chỉnh của bạn:
- curl -X POST -H "Content-Type: application/json" --data '{ "query": "{ bios { name { first, last } } }" }' http://example.com 
Thao tác này sẽ trả về đối tượng JSON giống như đối tượng của bước trước, bao gồm bất kỳ dữ liệu bổ sung nào mà bạn có thể đã thêm bằng cách sử dụng một đột biến:
Output{"data":{"bios":[{"name":{"first":"John","last":"Backus"}},{"name":{"first":"John","last":"McCarthy"}},{"name":{"first":"test","last":"user"}}]}} Đến đây bạn đã làm cho server GraphQL của bạn có thể truy cập từ xa, hãy đảm bảo server GraphQL của bạn không bị hỏng khi bạn đóng terminal hoặc server khởi động lại. Bằng cách này, database MongoDB của bạn có thể truy cập được thông qua server GraphQL khi nào bạn muốn đưa ra yêu cầu.
 Để thực hiện việc này, hãy sử dụng gói npm forever , một công cụ CLI  đảm bảo  các tập lệnh dòng lệnh của bạn chạy liên tục hoặc được khởi động lại trong trường hợp có bất kỳ lỗi nào.
 Cài đặt forever với npm:
- sudo npm install forever -g 
Sau khi cài đặt xong, hãy thêm nó vào file  package.json :
{   "name": "project_name",   "version": "1.0.0",   "description": "",   "main": "index.js",   "scripts": {     "start": "node index.js",     "deploy": "forever start --minUptime 2000 --spinSleepTime 5 index.js",     "test": "echo \"Error: no test specified\" && exit 1"   },   ... Để khởi động  server  GraphQL với kích hoạt forever , hãy chạy lệnh sau:
- npm run deploy 
Thao tác này sẽ khởi động index.js chứa  server  GraphQL forever và đảm bảo nó sẽ tiếp tục chạy với thời gian hoạt động tối thiểu là 2000 mili giây và 5 mili giây giữa mỗi lần khởi động lại trong trường hợp bị lỗi.  Server  GraphQL bây giờ sẽ liên tục chạy ở chế độ nền, vì vậy bạn không cần phải mở tab mới nữa khi muốn gửi yêu cầu đến  server .
Đến đây bạn đã tạo một server GraphQL đang sử dụng MongoDB để lưu trữ dữ liệu và được cài đặt để cho phép truy cập từ một server từ xa. Trong bước tiếp theo, bạn sẽ kích hoạt playground GraphiQL, điều này sẽ giúp bạn kiểm tra server GraphQL dễ dàng hơn.
Bước 5 - Bật playground GraphiQL
 Có thể gửi yêu cầu cURL đến  server  GraphQL là rất tốt, nhưng sẽ nhanh hơn nếu có giao diện  user  có thể thực thi các yêu cầu GraphQL ngay lập tức, đặc biệt là trong quá trình phát triển. Đối với điều này, bạn có thể sử dụng GraphiQL, một giao diện được hỗ trợ bởi gói express-graphql .
 Để bật GraphiQL, hãy chỉnh sửa file  index.js :
- sudo nano index.js 
Thêm các dòng được đánh dấu sau:
const app = express(); app.use('/graphql', graphqlHTTP({   schema,   rootValue: resolvers,   context,   graphiql: true })); app.listen(4000);  console.log(`🚀 Server ready at http://localhost:4000/graphql`); Lưu và thoát khỏi file .
 Để những thay đổi này hiển thị, hãy đảm bảo dừng forever bằng cách thực hiện:
- forever stop index.js 
Tiếp theo, bắt đầu lại forever để version  mới nhất của  server  GraphQL của bạn đang chạy:
- npm run deploy 
Mở trình duyệt tại URL http:// example.com , thay thế example.com bằng domain  hoặc IP  server  của bạn. Bạn sẽ thấy playground  GraphiQL, nơi bạn có thể nhập các yêu cầu GraphQL. 
Ở phía bên trái của playground này, bạn có thể nhập các truy vấn và đột biến GraphQL, trong khi kết quả sẽ được hiển thị ở phía bên phải của playground . Để kiểm tra xem điều này có hoạt động hay không, hãy nhập truy vấn sau ở phía bên trái:
query {   bios {     name {       first       last     }   } } Điều này sẽ xuất ra cùng một kết quả ở phía bên phải của playground , ở định dạng JSON:
Đến đây bạn có thể gửi yêu cầu GraphQL bằng terminal và playground GraphiQL.
Kết luận
Trong hướng dẫn này, bạn đã cài đặt database MongoDB và truy xuất và thay đổi dữ liệu từ database này bằng cách sử dụng GraphQL, Node.js và Express cho server . Ngoài ra, bạn đã cấu hình Nginx để cho phép truy cập từ xa vào server này. Bạn không chỉ có thể gửi yêu cầu đến server GraphQL này trực tiếp, bạn còn có thể sử dụng GraphiQL làm giao diện GraphQL trực quan trong trình duyệt.
Nếu bạn muốn tìm hiểu về GraphQL, bạn có thể xem bản ghi lại bài thuyết trình của tôi trên GraphQL tại NDC {London} hoặc truy cập trang web howtographql.com để xem hướng dẫn về GraphQL. Để nghiên cứu cách GraphQL tương tác với các công nghệ khác, hãy xem hướng dẫn về Cách cài đặt server Prisma theo cách thủ công trên Ubuntu 18.04 và để biết thêm thông tin về cách xây dựng ứng dụng với MongoDB, hãy xem Cách tạo blog với Nest.js, MongoDB và Vue.js.
Các tin liên quan
Cách thiết lập thủ công server Prisma trên Ubuntu 18.042019-01-11
Kết xuất phía server với Angular Universal
2019-01-10
Cách cài đặt và cấu hình pgAdmin 4 ở Chế độ server
2018-10-19
Cách cài đặt Linux, Apache, MySQL, PHP (LAMP) trên Debian 8
2018-10-18
Cách cài đặt Linux, Nginx, MySQL, PHP ( LEMP) trên Debian 9
2018-09-13
Cách cài đặt, chạy và kết nối với Jupyter Notebook trên server từ xa
2018-09-12
Cách cài đặt và cấu hình Postfix làm server SMTP chỉ gửi trên Debian 9
2018-09-07
Cách cấu hình BIND làm server DNS Mạng Riêng trên Debian 9
2018-09-06
Cách cài đặt Linux, Apache, MariaDB, PHP (LAMP) trên Debian 9
2018-09-04
Thiết lập server ban đầu với Debian 9
2018-09-04
 

