Thứ năm, 18/04/2019 | 00:00 GMT+7

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 :

Sân chơi GraphiQL đang hoạt động

Yêu cầu

Trước khi bắt đầu hướng dẫn này, bạn cần những thứ sau:

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ề:

Output
Successfully 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:

Output
Successfully 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:

/etc/mongodb.conf
... # 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 Expressexpress-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:

Output
v8.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:

Output
Wrote 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:

index.js
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:

index.js
... // 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:

index.js
... // 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:

index.js
... 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:

package.json
{   "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 , passworddatabase_name là những tên bạn đã tạo trong bước đầu tiên của hướng dẫn này.

index.js
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:

index.js
... 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:

index.js
... // 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à NameAwards , 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')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 :

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:

index.js
... // 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:

index.js
... // 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 :

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:

index.js
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:

/etc/nginx/sites-available/example.com
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:

Output
nginx: 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 :

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:

index.js
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.

Màn hình ban đầu cho playground  GraphiQL

Ở 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:

Sân chơi GraphiQL đang hoạt động

Đế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.


Tags:

Các tin liên quan

Cách thiết lập thủ công server Prisma trên Ubuntu 18.04
2019-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
Thiết lập server ban đầu với Debian 9
2018-09-04
Cách cài đặt Linux, Apache, MariaDB, PHP (LAMP) trên Debian 9
2018-09-04