Thứ tư, 13/02/2019 | 00:00 GMT+7

Cách tích hợp MongoDB với ứng dụng Node của bạn

Khi làm việc với Node.js , bạn có thể thấy mình đang phát triển một dự án lưu trữ và truy vấn dữ liệu. Trong trường hợp này, bạn cần phải chọn giải pháp database phù hợp với dữ liệu và kiểu truy vấn của ứng dụng.

Trong hướng dẫn này, bạn sẽ tích hợp database MongoDB với một ứng dụng Node hiện có. Database NoSQL như MongoDB có thể hữu ích nếu các yêu cầu dữ liệu bao gồm khả năng mở rộng và tính linh hoạt. MongoDB cũng tích hợp tốt với Node vì nó được thiết kế để hoạt động không đồng bộ với các đối tượng JSON .

Để tích hợp MongoDB vào dự án của bạn , bạn sẽ sử dụng Mongoose đối tượng lập bản đồ tài liệu (ODM) để tạo schemas và mô hình cho dữ liệu ứng dụng của bạn . Điều này sẽ cho phép bạn tổ chức mã ứng dụng của bạn theo mô hình kiến trúc model-view-controller (MVC) , cho phép bạn tách biệt logic về cách ứng dụng của bạn xử lý thông tin đầu vào của user với cách dữ liệu được cấu trúc và hiển thị cho user . Sử dụng mẫu này có thể tạo điều kiện thuận lợi cho việc thử nghiệm và phát triển trong tương lai bằng cách đưa vào cơ sở mã của bạn sự tách biệt các mối quan tâm.

Ở cuối hướng dẫn, bạn sẽ có một ứng dụng thông tin về cá mập đang hoạt động, ứng dụng này sẽ lấy thông tin đầu vào của user về những con cá mập yêu thích của họ và hiển thị kết quả trong trình duyệt:

Đầu ra cá mập

Yêu cầu

Bước 1 - Tạo user Mongo

Trước khi bắt đầu làm việc với mã ứng dụng, ta sẽ tạo một admin-user sẽ có quyền truy cập vào database ứng dụng của ta . User này sẽ có quyền quản trị trên bất kỳ database nào, điều này sẽ giúp bạn linh hoạt trong việc chuyển đổi và tạo database mới nếu cần.

Trước tiên, hãy kiểm tra xem MongoDB có đang chạy trên server của bạn không:

  • sudo systemctl status mongodb

Kết quả sau cho biết MongoDB đang chạy:

Output
● mongodb.service - An object/document-oriented database Loaded: loaded (/lib/systemd/system/mongodb.service; enabled; vendor preset: enabled) Active: active (running) since Thu 2019-01-31 21:07:25 UTC; 21min ago ...

Tiếp theo, mở shell Mongo để tạo user của bạn:

  • mongo

Điều này sẽ đưa bạn vào một shell quản trị:

Output
MongoDB shell version v3.6.3 connecting to: mongodb://127.0.0.1:27017 MongoDB server version: 3.6.3 ... >

Bạn sẽ thấy một số cảnh báo quản trị khi bạn mở shell do quyền truy cập không hạn chế của bạn vào database admin . Bạn có thể tìm hiểu thêm về cách hạn chế quyền truy cập này bằng cách đọc Cách cài đặt và bảo mật MongoDB trên Ubuntu 16.04 , khi bạn chuyển sang cài đặt production .

Hiện tại, bạn có thể sử dụng quyền truy cập của bạn vào database admin để tạo user có quyền userAdminAnyDatabase , cho phép truy cập được bảo vệ bằng password vào database của ứng dụng của bạn.

Trong shell, chỉ định rằng bạn muốn sử dụng database admin để tạo user của bạn :

  • use admin

Tiếp theo, tạo một role và password bằng cách thêm tên user và password bằng lệnh db.createUser . Sau khi bạn nhập lệnh này, shell sẽ thêm ba dấu chấm trước mỗi dòng cho đến khi lệnh hoàn tất. Đảm bảo thay thế user và password được cung cấp ở đây bằng tên user và password của bạn :

  • db.createUser(
  • {
  • user: "sammy",
  • pwd: "your_password",
  • roles: [ { role: "userAdminAnyDatabase", db: "admin" } ]
  • }
  • )

Điều này tạo một mục nhập cho sammy user trong database admin . Tên user bạn chọn và database admin sẽ đóng role là số nhận dạng cho user của bạn.

Đầu ra cho toàn bộ quá trình sẽ như thế này, bao gồm thông báo cho biết rằng mục nhập đã thành công:

Output
> db.createUser( ... { ... user: "sammy", ... pwd: "your_password", ... roles: [ { role: "userAdminAnyDatabase", db: "admin" } ] ... } ...) Successfully added user: { "user" : "sammy", "roles" : [ { "role" : "userAdminAnyDatabase", "db" : "admin" } ] }

Với user và password của bạn đã được tạo, bây giờ bạn có thể thoát khỏi Mongo shell:

  • exit

Đến đây bạn đã tạo user database của bạn , bạn có thể chuyển sang sao chép mã dự án khởi động và thêm thư viện Mongoose, cho phép bạn triển khai các schemas và mô hình cho các bộ sưu tập trong database của bạn .

Bước 2 - Thêm Mongoose và Thông tin Database vào Dự án

Các bước tiếp theo của ta sẽ là sao chép mã khởi động ứng dụng và thêm Mongoose và thông tin database MongoDB của ta vào dự án.

Trong folder chính của user không phải root của bạn, sao chép kho lưu trữ nodejs-image-demo từ tài khoản GitHub Cộng đồng DigitalOcean . Kho lưu trữ này bao gồm mã từ cài đặt được mô tả trong Cách tạo ứng dụng Node.js với Docker .

Sao node_project repository vào một folder có tên là node_project :

  • git clone https://github.com/do-community/nodejs-image-demo.git node_project

Thay đổi thành folder node_project :

  • cd node_project

Trước khi sửa đổi mã dự án, ta hãy xem cấu trúc của dự án bằng lệnh tree .

Mẹo: tree là một lệnh hữu ích để xem cấu trúc file và folder từ dòng lệnh. Bạn có thể cài đặt nó bằng lệnh sau:

  • sudo apt install tree

Để sử dụng nó, hãy cd vào một folder nhất định và gõ tree . Bạn cũng có thể cung cấp đường dẫn đến điểm bắt đầu bằng lệnh như:

  • tree /home/sammy/sammys-project

node_project sau để xem folder node_project :

  • tree

Cấu trúc của dự án hiện tại trông như thế này:

Output
├── Dockerfile ├── README.md ├── app.js ├── package-lock.json ├── package.json └── views ├── css │ └── styles.css ├── index.html └── sharks.html

Ta sẽ thêm các folder vào dự án này khi ta chuyển qua hướng dẫn và tree sẽ là một lệnh hữu ích để giúp ta theo dõi tiến trình của bạn .

Tiếp theo, thêm gói npm mongoose vào dự án bằng lệnh npm install :

  • npm install mongoose

Lệnh này sẽ tạo một folder node_modules trong folder dự án của bạn, sử dụng các phần phụ thuộc được liệt kê trong file package.json của dự án và sẽ thêm mongoose vào folder đó. Nó cũng sẽ thêm mongoose vào các phụ thuộc được liệt kê trong file package.json của bạn. Để có thảo luận chi tiết hơn về package.json , vui lòng xem Bước 1 trong Cách tạo ứng dụng Node.js với Docker .

Trước khi tạo bất kỳ schemas hoặc mô hình Mongoose nào, ta sẽ thêm thông tin kết nối database để ứng dụng của ta có thể kết nối với database của ta .

Để tách biệt các mối quan tâm của ứng dụng của bạn nhiều nhất có thể, hãy tạo một file riêng cho thông tin kết nối database của bạn có tên là db.js Bạn có thể mở file này bằng nano hoặc editor bạn quen dùng :

  • nano db.js

Thứ nhất, nhập khẩu các mongoose mô-đun bằng cách sử dụng require chức năng:

~ / node_project / db.js
const mongoose = require('mongoose'); 

Điều này sẽ cung cấp cho bạn quyền truy cập vào các phương thức có sẵn của Mongoose, mà bạn sẽ sử dụng để tạo kết nối với database của bạn .

Tiếp theo, thêm các hằng số sau để xác định thông tin cho URI kết nối của Mongo. Mặc dù tên user và password là tùy chọn, ta sẽ bao gồm chúng để ta có thể yêu cầu xác thực cho database của bạn . Đảm bảo thay thế tên user và password được liệt kê bên dưới bằng thông tin của bạn và vui lòng gọi database là gì đó khác với ' sharkinfo ' nếu bạn muốn:

~ / node_project / db.js
const mongoose = require('mongoose');  const MONGO_USERNAME = 'sammy'; const MONGO_PASSWORD = 'your_password'; const MONGO_HOSTNAME = '127.0.0.1'; const MONGO_PORT = '27017'; const MONGO_DB = 'sharkinfo'; 

Bởi vì ta đang chạy database của bạn local , ta đã sử dụng 127.0.0.1 làm tên server . Điều này sẽ thay đổi trong các bối cảnh phát triển khác: ví dụ: nếu bạn đang sử dụng một server database riêng biệt hoặc làm việc với nhiều nút trong quy trình làm việc được chứa.

Cuối cùng, xác định một hằng số cho URI và tạo kết nối bằng phương thức mongoose.connect() :

~ / node_project / db.js
... const url = `mongodb://${MONGO_USERNAME}:${MONGO_PASSWORD}@${MONGO_HOSTNAME}:${MONGO_PORT}/${MONGO_DB}?authSource=admin`;  mongoose.connect(url, {useNewUrlParser: true}); 

Lưu ý trong URI, ta đã chỉ định authSource cho user của ta làm database admin . Điều này là cần thiết vì ta đã chỉ định tên user trong chuỗi kết nối của bạn . Sử dụng cờ useNewUrlParser với mongoose.connect() chỉ định rằng ta muốn sử dụng trình phân tích cú pháp URL mới của Mongo.

Lưu file khi bạn hoàn tất chỉnh sửa.

Bước cuối cùng, hãy thêm thông tin kết nối database vào file app.js để ứng dụng có thể sử dụng. Mở app.js :

  • nano app.js

Các dòng đầu tiên của file sẽ giống như sau:

~ / node_project / app.js
const express = require('express'); const app = express(); const router = express.Router();  const path = __dirname + '/views/'; ... 

Bên dưới router nghĩa hằng số router , nằm gần đầu file , thêm dòng sau:

~ / node_project / app.js
... const router = express.Router(); const db = require('./db');  const path = __dirname + '/views/'; ... 

Điều này yêu cầu ứng dụng sử dụng thông tin kết nối database được chỉ định trong db.js

Lưu file khi bạn hoàn tất chỉnh sửa.

Với thông tin database của bạn đã có sẵn và Mongoose được thêm vào dự án của bạn, bạn đã sẵn sàng tạo các schemas và mô hình sẽ định hình dữ liệu trong bộ sưu tập sharks của bạn.

Bước 3 - Tạo các mô hình và schemas Mongoose

Bước tiếp theo của ta sẽ là suy nghĩ về cấu trúc của bộ sưu tập sharks mà user sẽ tạo trong database sharkinfo với thông tin đầu vào của họ. Ta muốn các tài liệu đã tạo này có cấu trúc nào? Trang thông tin về cá mập trong ứng dụng hiện tại của ta bao gồm một số chi tiết về các loài cá mập khác nhau và hành vi của chúng:

Trang thông tin cá mập

Để phù hợp với chủ đề này, ta có thể yêu cầu user thêm những con cá mập mới với thông tin chi tiết về nhân vật tổng thể của chúng. Mục tiêu này sẽ định hình cách ta tạo schemas của bạn .

Để giữ cho các schemas và mô hình của bạn khác biệt với các phần khác của ứng dụng, hãy tạo một folder models trong folder dự án hiện tại:

  • mkdir models

Tiếp theo, mở một file có tên là sharks.js để tạo schemas và mô hình của bạn:

  • nano models/sharks.js

Nhập module mongoose ở đầu file :

~ / node_project / models / shark.js
const mongoose = require('mongoose'); 

Dưới đây, xác định một đối tượng Schema để sử dụng làm cơ sở cho schemas cá mập của bạn:

~ / node_project / models / shark.js
const mongoose = require('mongoose'); const Schema = mongoose.Schema; 

Đến đây bạn có thể xác định các trường bạn muốn đưa vào schemas của bạn . Vì ta muốn tạo một bộ sưu tập với các cá mập riêng lẻ và thông tin về các hành vi của chúng, hãy bao gồm khóa name và khóa character . Thêm schemas Shark sau bên dưới các định nghĩa hằng số của bạn:

~ / node_project / models / shark.js
... const Shark = new Schema ({         name: { type: String, required: true },         character: { type: String, required: true }, }); 

Định nghĩa này bao gồm thông tin về loại đầu vào mà ta mong đợi từ user - trong trường hợp này là một chuỗi - và liệu đầu vào đó có được yêu cầu hay không.

Cuối cùng, tạo mô hình Shark bằng cách sử dụng hàm model() của Mongoose. Mô hình này sẽ cho phép bạn truy vấn các tài liệu từ bộ sưu tập của bạn và xác nhận các tài liệu mới. Thêm dòng sau vào cuối file :

~ / node_project / models / shark.js
... module.exports = mongoose.model('Shark', Shark) 

Dòng cuối cùng này làm cho mô hình Shark của ta có sẵn dưới dạng module bằng cách sử dụng thuộc tính module.exports . Thuộc tính này xác định các giá trị mà module sẽ xuất, làm cho chúng có sẵn để sử dụng ở những nơi khác trong ứng dụng.

Tệp models/sharks.js đã hoàn thành trông giống như sau:

~ / node_project / models / shark.js
const mongoose = require('mongoose'); const Schema = mongoose.Schema;  const Shark = new Schema ({         name: { type: String, required: true },         character: { type: String, required: true }, });  module.exports = mongoose.model('Shark', Shark) 

Lưu file khi bạn hoàn tất chỉnh sửa.

Với schemas và mô hình Shark , bạn có thể bắt đầu làm việc trên logic sẽ xác định cách ứng dụng của bạn sẽ xử lý đầu vào của user .

Bước 4 - Tạo bộ điều khiển

Bước tiếp theo của ta sẽ là tạo thành phần bộ điều khiển sẽ xác định cách thức nhập liệu của user được lưu vào database của ta và trả lại cho user .

Đầu tiên, tạo một folder cho bộ điều khiển:

  • mkdir controllers

Tiếp theo, mở một file trong folder đó có tên là sharks.js :

  • nano controllers/sharks.js

Ở đầu file , ta sẽ nhập module với mô hình Shark của ta để ta có thể sử dụng nó trong logic của bộ điều khiển. Ta cũng sẽ nhập mô-đun path để truy cập các tiện ích cho phép ta đặt đường dẫn đến biểu mẫu mà user sẽ nhập cá mập của họ.

Thêm các hàm require sau vào đầu file :

~ / node_project / controllers / shark.js
const path = require('path'); const Shark = require('../models/sharks'); 

Tiếp theo, ta sẽ viết một chuỗi các hàm mà ta sẽ xuất với module bộ điều khiển bằng cách sử dụng phím tắt exports của Node. Các chức năng này sẽ bao gồm ba tác vụ liên quan đến dữ liệu cá mập của user của ta :

  • Gửi cho user biểu mẫu đầu vào cá mập.
  • Tạo một mục cá mập mới.
  • Hiển thị lại cá mập cho user .

Để bắt đầu, hãy tạo một hàm index để hiển thị trang cá mập với biểu mẫu đầu vào. Thêm chức năng này bên dưới nhập của bạn:

~ / node_project / controllers / shark.js
... exports.index = function (req, res) {     res.sendFile(path.resolve('views/sharks.html')); }; 

Tiếp theo, bên dưới hàm index , hãy thêm một hàm có tên là create để tạo một mục nhập cá mập mới trong bộ sưu tập sharks của bạn:

~ / node_project / controllers / shark.js
... exports.create = function (req, res) {     var newShark = new Shark(req.body);     console.log(req.body);     newShark.save(function (err) {             if(err) {             res.status(400).send('Unable to save shark to database');         } else {             res.redirect('/sharks/getshark');         }   });                }; 

Hàm này sẽ được gọi khi user đăng dữ liệu cá mập vào biểu mẫu trên trang sharks.html . Ta sẽ tạo tuyến với điểm cuối POST này ở phần sau của hướng dẫn khi ta tạo các tuyến ứng dụng của bạn . Với phần body của yêu cầu POST, hàm create của ta sẽ tạo một đối tượng tài liệu cá mập mới, ở đây được gọi là newShark , sử dụng mô hình Shark mà ta đã nhập. Ta đã thêm một phương thức console.log để xuất mục nhập cá mập vào console nhằm kiểm tra xem phương thức POST của ta có hoạt động như dự kiến hay không, nhưng bạn có thể bỏ qua điều này nếu muốn.

Sử dụng đối tượng newShark , hàm create sau đó sẽ gọi phương thức model.save() của Mongoose để tạo một tài liệu cá mập mới bằng cách sử dụng các khóa bạn đã xác định trong mô hình Shark . Hàm gọi lại này tuân theo mô hình gọi lại Node tiêu chuẩn : callback(error, results) . Trong trường hợp xảy ra lỗi, ta sẽ gửi thông báo báo lỗi cho user của ta và trong trường hợp thành công, ta sẽ sử dụng phương thức res.redirect() để đưa user đến điểm cuối sẽ hiển thị thông tin cá mập của họ trở lại chúng trong trình duyệt.

Cuối cùng, chức năng list sẽ hiển thị lại nội dung của bộ sưu tập cho user . Thêm mã sau vào bên dưới hàm create :

~ / node_project / controllers / shark.js
... exports.list = function (req, res) {         Shark.find({}).exec(function (err, sharks) {                 if (err) {                         return res.send(500, err);                 }                 res.render('getshark', {                         sharks: sharks              });         }); }; 

Hàm này sử dụng mô hình Shark với phương thức model.find() của Mongoose để trả về các cá mập đã được nhập vào bộ sưu tập sharks . Nó thực hiện điều này bằng cách trả về đối tượng truy vấn - trong trường hợp này là tất cả các mục trong bộ sưu tập sharks - như một lời hứa, bằng cách sử dụng hàm executive exec() của Mongoose. Trong trường hợp có lỗi, chức năng gọi lại sẽ gửi lỗi 500.

Đối tượng truy vấn được trả về với bộ sưu tập sharks sẽ được hiển thị trong một trang getshark mà ta sẽ tạo trong bước tiếp theo bằng cách sử dụng ngôn ngữ tạo khuôn mẫu EJS .

Tệp đã hoàn thành sẽ giống như sau:

~ / node_project / controllers / shark.js
const path = require('path'); const Shark = require('../models/sharks');  exports.index = function (req, res) {     res.sendFile(path.resolve('views/sharks.html')); };  exports.create = function (req, res) {     var newShark = new Shark(req.body);     console.log(req.body);     newShark.save(function (err) {             if(err) {             res.status(400).send('Unable to save shark to database');         } else {             res.redirect('/sharks/getshark');         }   });                };  exports.list = function (req, res) {         Shark.find({}).exec(function (err, sharks) {                 if (err) {                         return res.send(500, err);                 }                 res.render('getshark', {                         sharks: sharks              });         }); }; 

Lưu ý mặc dù ta không sử dụng các hàm mũi tên ở đây, bạn có thể cần đưa chúng vào khi lặp lại mã này trong quá trình phát triển của riêng mình.

Lưu file khi bạn hoàn tất chỉnh sửa.

Trước khi chuyển sang bước tiếp theo, bạn có thể chạy lại tree từ folder node_project của bạn để xem cấu trúc của dự án tại thời điểm này. Lần này, để ngắn gọn, ta sẽ yêu cầu tree bỏ qua folder node_modules bằng cách sử dụng tùy chọn -I :

  • tree -I node_modules

Với những bổ sung bạn đã thực hiện, cấu trúc dự án của bạn sẽ giống như sau:

Output
├── Dockerfile ├── README.md ├── app.js ├── controllers │ └── sharks.js ├── db.js ├── models │ └── sharks.js ├── package-lock.json ├── package.json └── views ├── css │ └── styles.css ├── index.html └── sharks.html

Đến đây bạn đã có một thành phần bộ điều khiển để hướng dẫn cách thức nhập liệu của user được lưu và trả lại cho user , bạn có thể chuyển sang tạo các khung nhìn sẽ triển khai logic của bộ điều khiển của bạn.

Bước 5 - Sử dụng EJS và Express Middleware để thu thập và kết xuất dữ liệu

Để cho phép ứng dụng của ta hoạt động với dữ liệu user , ta sẽ thực hiện hai việc: đầu tiên, ta sẽ bao gồm một chức năng phần mềm trung gian Express tích hợp sẵn, urlencoded() , cho phép ứng dụng của ta phân tích dữ liệu đã nhập của user . Thứ hai, ta sẽ thêm các thẻ mẫu vào chế độ xem của bạn để cho phép tương tác động với dữ liệu user trong mã của ta .

Để làm việc với hàm urlencoded() của Express, trước tiên hãy mở file app.js của bạn:

  • nano app.js

Bên trên hàm express.static() , hãy thêm dòng sau:

~ / node_project / app.js
... app.use(express.urlencoded({ extended: true })); app.use(express.static(path)); ... 

Thêm chức năng này sẽ cho phép truy cập vào dữ liệu POST được phân tích cú pháp từ biểu mẫu thông tin cá mập của ta . Ta đang chỉ định true với tùy chọn extended để cho phép linh hoạt hơn trong loại dữ liệu mà ứng dụng của ta sẽ phân tích cú pháp (bao gồm những thứ như các đối tượng lồng nhau). Vui lòng xem tài liệu chức năng để biết thêm thông tin về các tùy chọn.

Lưu file khi bạn hoàn tất chỉnh sửa.

Tiếp theo, ta sẽ thêm chức năng mẫu vào chế độ xem của ta . Đầu tiên, hãy cài đặt gói ejs với npm install :

  • npm install ejs

Tiếp theo, mở file sharks.html trong folder views :

  • nano views/sharks.html

Ở Bước 3, ta đã xem trang này để xác định cách ta nên viết schemas và mô hình Mongoose của bạn :

Trang thông tin cá mập

Bây giờ, thay vì có bố cục hai cột, ta sẽ giới thiệu cột thứ ba với biểu mẫu nơi user có thể nhập thông tin về cá mập.

Bước đầu tiên, hãy thay đổi kích thước của các cột hiện có thành 4 để tạo ba cột có kích thước bằng nhau. Lưu ý bạn cần thực hiện thay đổi này trên hai dòng hiện đang đọc <div class="col-lg-6"> . Cả hai đều sẽ trở thành <div class="col-lg- 4 "> :

~ / node_project / views / shark.html
... <div class="container">     <div class="row">         <div class="col-lg-4">             <p>                 <div class="caption">Some sharks are known to be dangerous to humans, though many more are not. The sawshark, for example, is not considered a threat to humans.                 </div>                 <img src="https://assets.digitalocean.com/articles/docker_node_image/sawshark.jpg" alt="Sawshark">             </p>         </div>         <div class="col-lg-4">             <p>                 <div class="caption">Other sharks are known to be friendly and welcoming!</div>                 <img src="https://assets.digitalocean.com/articles/docker_node_image/sammy.png" alt="Sammy the Shark">             </p>         </div>     </div>   </div>   </html>  

Để biết phần giới thiệu về hệ thống lưới của Bootstrap, bao gồm bố cục hàng và cột của nó, vui lòng xem phần giới thiệu này về Bootstrap .

Tiếp theo, thêm một cột khác bao gồm điểm cuối được đặt tên cho yêu cầu ĐĂNG với dữ liệu cá mập của user và các thẻ mẫu EJS sẽ nắm bắt dữ liệu đó. Cột này sẽ nằm bên dưới các </p> đóng </p></div> từ cột trước đó và phía trên các thẻ đóng cho hàng, containers và trang HTML . Các thẻ đóng này đã được đặt sẵn trong mã của bạn; chúng cũng được đánh dấu bên dưới với các comment . Giữ nguyên chúng khi bạn thêm mã sau để tạo cột mới:

~ / node_project / views / shark.html
...        </p> <!-- closing p from previous column -->    </div> <!-- closing div from previous column --> <div class="col-lg-4">             <p>                 <form action="/sharks/addshark" method="post">                     <div class="caption">Enter Your Shark</div>                     <input type="text" placeholder="Shark Name" name="name" <%=sharks[i].name; %>                     <input type="text" placeholder="Shark Character" name="character" <%=sharks[i].character; %>                     <button type="submit">Submit</button>                 </form>             </p>         </div>      </div> <!-- closing div for row --> </div> <!-- closing div for container -->  </html> <!-- closing html tag --> 

Trong thẻ form , bạn đang thêm điểm cuối "/sharks/addshark" cho dữ liệu cá mập của user và chỉ định phương thức POST để gửi dữ liệu đó. Trong các trường đầu vào, bạn đang chỉ định các trường cho "Shark Name""Shark Character" , phù hợp với mô hình Shark bạn đã xác định trước đó.

Để thêm đầu vào của user vào bộ sưu tập sharks của bạn, bạn đang sử dụng các thẻ mẫu EJS ( <%= , %> ) cùng với cú pháp JavaScript để ánh xạ các mục nhập của user đến các trường thích hợp trong tài liệu mới được tạo. Để biết thêm về các đối tượng JavaScript, vui lòng xem bài viết của ta về Tìm hiểu các đối tượng JavaScript . Để biết thêm về các thẻ mẫu EJS, vui lòng xem tài liệu EJS .

Toàn bộ containers có tất cả ba cột, bao gồm cả cột có biểu mẫu nhập cá mập của bạn, sẽ trông như thế này khi hoàn tất:

~ / node_project / views / shark.html
... <div class="container">     <div class="row">         <div class="col-lg-4">             <p>                 <div class="caption">Some sharks are known to be dangerous to humans, though many more are not. The sawshark, for example, is not considered a threat to humans.                 </div>                 <img src="https://assets.digitalocean.com/articles/docker_node_image/sawshark.jpg" alt="Sawshark">             </p>         </div>         <div class="col-lg-4">             <p>                 <div class="caption">Other sharks are known to be friendly and welcoming!</div>                 <img src="https://assets.digitalocean.com/articles/docker_node_image/sammy.png" alt="Sammy the Shark">             </p>         </div>     <div class="col-lg-4">             <p>                 <form action="/sharks/addshark" method="post">                     <div class="caption">Enter Your Shark</div>                     <input type="text" placeholder="Shark Name" name="name" <%=sharks[i].name; %>                     <input type="text" placeholder="Shark Character" name="character" <%=sharks[i].character; %>                     <button type="submit">Submit</button>                 </form>             </p>         </div>     </div>   </div>  </html> 

Lưu file khi bạn hoàn tất chỉnh sửa.

Đến đây bạn đã có cách để thu thập thông tin đầu vào của user , bạn có thể tạo một điểm cuối để hiển thị những con cá mập đã trả lại và thông tin nhân vật liên quan của chúng.

Sao chép file sharks.html mới được sửa đổi vào file có tên là getshark.html :

  • cp views/sharks.html views/getshark.html

Mở getshark.html :

  • nano views/getshark.html

Bên trong file , ta sẽ sửa đổi cột mà ta đã sử dụng để tạo biểu mẫu nhập cá mập bằng cách thay thế nó bằng một cột sẽ hiển thị các cá mập trong bộ sưu tập sharks của ta . , mã của bạn sẽ nằm giữa các </p></div> từ cột trước đó và các thẻ đóng cho hàng, containers và trang HTML . Hãy nhớ giữ nguyên các thẻ này khi bạn thêm mã sau để tạo cột:

~ / node_project / views / gethark.html
...        </p> <!-- closing p from previous column -->    </div> <!-- closing div from previous column --> <div class="col-lg-4">            <p>               <div class="caption">Your Sharks</div>                   <ul>                      <% sharks.forEach(function(shark) { %>                         <p>Name: <%= shark.name %></p>                         <p>Character: <%= shark.character %></p>                      <% }); %>                   </ul>             </p>         </div>     </div> <!-- closing div for row --> </div> <!-- closing div for container -->  </html> <!-- closing html tag --> 

Ở đây bạn đang sử dụng các thẻ mẫu EJS và phương thức forEach() để xuất từng giá trị trong bộ sưu tập sharks của bạn , bao gồm thông tin về loài cá mập được thêm mới nhất .

Toàn bộ containers có cả ba cột, bao gồm cả cột có bộ sưu tập sharks của bạn, sẽ trông như thế này khi hoàn thành:

~ / node_project / views / gethark.html
... <div class="container">     <div class="row">         <div class="col-lg-4">             <p>                 <div class="caption">Some sharks are known to be dangerous to humans, though many more are not. The sawshark, for example, is not considered a threat to humans.                 </div>                 <img src="https://assets.digitalocean.com/articles/docker_node_image/sawshark.jpg" alt="Sawshark">             </p>         </div>         <div class="col-lg-4">             <p>                 <div class="caption">Other sharks are known to be friendly and welcoming!</div>                 <img src="https://assets.digitalocean.com/articles/docker_node_image/sammy.png" alt="Sammy the Shark">             </p>         </div>     <div class="col-lg-4">             <p>               <div class="caption">Your Sharks</div>                   <ul>                      <% sharks.forEach(function(shark) { %>                         <p>Name: <%= shark.name %></p>                         <p>Character: <%= shark.character %></p>                      <% }); %>                   </ul>             </p>         </div>     </div>   </div>  </html> 

Lưu file khi bạn hoàn tất chỉnh sửa.

Để ứng dụng sử dụng các mẫu bạn đã tạo, bạn cần thêm một vài dòng vào file app.js của bạn . Mở lại:

  • nano app.js

Ở trên nơi bạn đã thêm hàm express.urlencoded() , hãy thêm các dòng sau:

~ / node_project / app.js
... app.engine('html', require('ejs').renderFile); app.set('view engine', 'html'); app.use(express.urlencoded({ extended: true })); app.use(express.static(path));  ... 

Phương thức app.engine yêu cầu ứng dụng ánh xạ công cụ mẫu EJS tới các file HTML, trong khi app.set xác định công cụ xem mặc định.

Tệp app.js của bạn bây giờ sẽ giống như sau:

~ / node_project / app.js
const express = require('express'); const app = express(); const router = express.Router(); const db = require('./db');  const path = __dirname + '/views/'; const port = 8080;  router.use(function (req,res,next) {   console.log('/' + req.method);   next(); });  router.get('/',function(req,res){   res.sendFile(path + 'index.html'); });  router.get('/sharks',function(req,res){   res.sendFile(path + 'sharks.html'); });  app.engine('html', require('ejs').renderFile); app.set('view engine', 'html'); app.use(express.urlencoded({ extended: true })); app.use(express.static(path)); app.use('/', router);  app.listen(port, function () {   console.log('Example app listening on port 8080!') }) 

Đến đây bạn đã tạo các khung nhìn có thể hoạt động động với dữ liệu user , đã đến lúc tạo các tuyến của dự án để tập hợp các khung nhìn và logic bộ điều khiển của bạn.

Bước 6 - Tạo các tuyến đường

Bước cuối cùng để kết hợp các thành phần của ứng dụng lại với nhau sẽ là tạo các tuyến. Ta sẽ phân tách các tuyến đường của bạn theo chức năng, bao gồm một tuyến đường đến trang đích của ứng dụng và một tuyến đường khác đến trang cá mập của ta . Lộ trình sharks của ta sẽ là nơi ta tích hợp logic của bộ điều khiển của ta với các khung nhìn mà ta đã tạo ở bước trước.

Đầu tiên, tạo một folder định routes :

  • mkdir routes

Tiếp theo, mở một file có tên là index.js trong folder này:

  • nano routes/index.js

Trước tiên, file này sẽ nhập các đối tượng express , routerpath , cho phép ta xác định các tuyến đường mà ta muốn xuất với đối tượng router và giúp nó có thể hoạt động động với các đường dẫn file . Thêm mã sau vào đầu file :

~ / node_project / route / index.js
const express = require('express'); const router = express.Router(); const path = require('path'); 

Tiếp theo, thêm hàm router.use sau, hàm này tải một chức năng phần mềm trung gian sẽ ghi lại các yêu cầu của bộ định tuyến và chuyển chúng vào tuyến của ứng dụng:

~ / node_project / route / index.js
...  router.use (function (req,res,next) {   console.log('/' + req.method);   next(); }); 

Các yêu cầu tới folder root của ứng dụng của ta sẽ được chuyển đến đây trước tiên và từ đây user sẽ được dẫn đến trang đích của ứng dụng của ta , lộ trình mà ta sẽ xác định tiếp theo. Thêm mã sau vào bên dưới hàm router.use để xác định đường dẫn đến trang đích:

~ / node_project / route / index.js
...  router.get('/',function(req,res){   res.sendFile(path.resolve('views/index.html')); }); 

Khi user truy cập ứng dụng của ta , nơi đầu tiên ta muốn đưa họ đến trang đích index.html mà ta có trong folder views .

Cuối cùng, để làm cho các tuyến này có thể truy cập được dưới dạng module có thể nhập ở nơi khác trong ứng dụng, hãy thêm biểu thức đóng vào cuối file để xuất đối tượng router :

~ / node_project / route / index.js
...  module.exports = router; 

Tệp đã hoàn thành sẽ giống như sau:

~ / node_project / route / index.js
const express = require('express'); const router = express.Router(); const path = require('path');  router.use (function (req,res,next) {   console.log('/' + req.method);   next(); });  router.get('/',function(req,res){   res.sendFile(path.resolve('views/index.html')); });  module.exports = router; 

Lưu file này khi bạn hoàn tất chỉnh sửa.

Tiếp theo, mở một file có tên sharks.js để xác định cách ứng dụng sẽ sử dụng các điểm cuối và chế độ xem khác nhau mà ta đã tạo để làm việc với đầu vào cá mập của user :

  • nano routes/sharks.js

Ở đầu file , nhập các đối tượng expressrouter :

~ / node_project / route / shark.js
const express = require('express'); const router = express.Router(); 

Tiếp theo, nhập một module có tên shark sẽ cho phép bạn làm việc với các chức năng đã xuất mà bạn đã xác định với bộ điều khiển của bạn :

~ / node_project / route / shark.js
const express = require('express'); const router = express.Router(); const shark = require('../controllers/sharks'); 

Như vậy, bạn có thể tạo các tuyến đường bằng cách sử dụng index , createlist hàm mà bạn đã xác định trong file điều khiển sharks của bạn . Mỗi tuyến đường sẽ được liên kết với phương thức HTTP thích hợp: NHẬN trong trường hợp hiển thị trang đích thông tin cá mập chính và trả lại danh sách cá mập cho user và ĐĂNG trong trường hợp tạo mục nhập cá mập mới:

~ / node_project / route / shark.js
...  router.get('/', function(req, res){     shark.index(req,res); });  router.post('/addshark', function(req, res) {     shark.create(req,res); });  router.get('/getshark', function(req, res) {     shark.list(req,res); }); 

Mỗi tuyến sử dụng chức năng có liên quan trong controllers/sharks.js , vì ta đã làm cho module đó có thể truy cập được bằng lệnh nó ở đầu file này.

Cuối cùng, đóng file bằng cách đính kèm các tuyến đường này vào đối tượng router và xuất chúng:

~ / node_project / route / index.js
...  module.exports = router; 

Tệp đã hoàn thành sẽ giống như sau:

~ / node_project / route / shark.js
const express = require('express'); const router = express.Router(); const shark = require('../controllers/sharks');  router.get('/', function(req, res){     shark.index(req,res); });  router.post('/addshark', function(req, res) {     shark.create(req,res); });  router.get('/getshark', function(req, res) {     shark.list(req,res); });  module.exports = router; 

Lưu file khi bạn hoàn tất chỉnh sửa.

Bước cuối cùng để làm cho các tuyến đường này có thể truy cập được vào ứng dụng của bạn là thêm chúng vào app.js Mở lại file đó:

  • nano app.js

Bên dưới hằng số db của bạn, hãy thêm nhập sau cho các tuyến đường của bạn:

~ / node_project / app.js
... const db = require('./db'); const sharks = require('./routes/sharks'); 

Tiếp theo, thay thế hàm app.use hiện đang gắn đối tượng router của bạn bằng dòng sau, dòng này sẽ gắn module bộ định tuyến sharks :

~ / node_project / app.js
... app.use(express.static(path)); app.use('/sharks', sharks);  app.listen(port, function () {         console.log("Example app listening on port 8080!") }) 

Đến đây bạn có thể xóa các tuyến đường đã được định nghĩa đó trong file này, vì bạn đang nhập các tuyến đường của ứng dụng bằng module bộ định tuyến sharks .

Phiên bản cuối cùng của file app.js của bạn sẽ trông giống như sau:

~ / node_project / app.js
const express = require('express'); const app = express(); const router = express.Router(); const db = require('./db'); const sharks = require('./routes/sharks');  const path = __dirname + '/views/'; const port = 8080;  app.engine('html', require('ejs').renderFile); app.set('view engine', 'html'); app.use(express.urlencoded({ extended: true })); app.use(express.static(path)); app.use('/sharks', sharks);  app.listen(port, function () {   console.log('Example app listening on port 8080!') }) 

Lưu file khi bạn hoàn tất chỉnh sửa.

Đến đây bạn có thể chạy lại tree để xem cấu trúc cuối cùng của dự án của bạn :

  • tree -I node_modules

Cấu trúc dự án của bạn bây giờ sẽ giống như sau:

Output
├── Dockerfile ├── README.md ├── app.js ├── controllers │ └── sharks.js ├── db.js ├── models │ └── sharks.js ├── package-lock.json ├── package.json ├── routes │ ├── index.js │ └── sharks.js └── views ├── css │ └── styles.css ├── getshark.html ├── index.html └── sharks.html

Với tất cả các thành phần ứng dụng của bạn đã được tạo và tại chỗ, bây giờ bạn đã sẵn sàng thêm một con cá mập thử nghiệm vào database của bạn !

Nếu bạn đã làm theo hướng dẫn cài đặt server ban đầu trong yêu cầu , bạn cần phải sửa đổi firewall của bạn , vì nó hiện chỉ cho phép lưu lượng SSH. Để cho phép giao thông đến cổng 8080 chạy:

  • sudo ufw allow 8080

Khởi động ứng dụng:

  • node app.js

Tiếp theo, chuyển trình duyệt của bạn đến http:// your_server_ip :8080 . Bạn sẽ thấy trang đích sau:

Trang đích ứng dụng

Nhấp vào nút Nhận thông tin cá mập . Bạn sẽ thấy trang thông tin sau, với biểu mẫu nhập cá mập được thêm vào:

Biểu mẫu thông tin cá mập

Trong biểu mẫu, hãy thêm một con cá mập mà bạn chọn. Với mục đích của phần trình diễn này, ta sẽ thêm Megalodon Shark vào trường Shark NameAncient vào trường Shark Character :

Hình thức cá mập đầy

Bấm vào nút Gửi . Bạn sẽ thấy một trang với thông tin cá mập này được hiển thị lại cho bạn:

Đầu ra cá mập

Bạn cũng sẽ thấy kết quả trong console của bạn cho biết rằng con cá mập đã được thêm vào bộ sưu tập của bạn:

Output
Example app listening on port 8080! { name: 'Megalodon Shark', character: 'Ancient' }

Nếu bạn muốn tạo mục nhập cá mập mới, hãy quay lại trang Cá mập và lặp lại quy trình thêm cá mập.

Đến đây bạn có một ứng dụng thông tin cá mập đang hoạt động cho phép user thêm thông tin về những con cá mập yêu thích của họ.

Kết luận

Trong hướng dẫn này, bạn đã xây dựng một ứng dụng Node bằng cách tích hợp database MongoDB và viết lại logic của ứng dụng bằng cách sử dụng mẫu kiến trúc MVC. Ứng dụng này có thể hoạt động như một điểm khởi đầu tốt cho một ứng dụng CRUD chính thức.

Để biết thêm tài nguyên về mẫu MVC trong các ngữ cảnh khác, vui lòng xem loạt bài Phát triển Django của ta hoặc Cách Xây dựng Ứng dụng Web Hiện đại để Quản lý Thông tin Khách hàng với Django và React trên Ubuntu 18.04 .

Để biết thêm thông tin về cách làm việc với MongoDB, vui lòng xem thư viện hướng dẫn của ta về MongoDB .


Tags:

Các tin liên quan