Hướng dẫn phân trang trong danh sách dữ liệu API viết bằng nodejs

d52bb1 2024

Bài viết hướng dẫn cơ bản nhất về viết một ứng dụng nodejs có kết nối mongodb lấy danh sách bài viết sau đó phân trang.

Bước 1: Cài mongodb trên máy cá nhân nếu chưa có

Bạn có thể dùng bản mongo online nhưng sẽ có giới hạn về lưu trữ và có ảnh hưởng bởi tốc độ đường truyền internet và cấu hình IP.

- Link tải mongodb server https://www.mongodb.com/try/download/community 

- Link tải công cụ compass để có giao diện quản lý mongodb https://www.mongodb.com/en-us/products/tools/compass

Sau khi bạn cài đặt xong (cài đủ 2 thứ trên) bạn mở compass đã cài đặt, mặc định sẽ hiển thị một kết nối mẫu, bạn bấm vào Connect để bắt đầu kết nối sẽ vào được giao diện quản lý Mongo.

Cách sử dụng phần mềm và các thao tác trên đó sẽ giới thiệu ở bài viết khác, bạn có thể tra cứu thêm trên internet.

Bước 2: Tạo ứng dụng Nodejs với express-generator

Bạn mở phần mền VS Code hoặc cửa sổ lệnh, đứng tại thư mục sẽ chứa code ứng dụng bạn chạy các lệnh sau:

- Chạy lệnh cài express-generator để tạo code

npm install -g express-generator

- Chạy tiếp lệnh tạo project với tên project là Api_Zezo_Dev

express --view=ejs Api_Zezo_Dev

- Tiếp theo CD vào thư mục code vừa tạo

cd Api_Zezo_Dev

- Tiếp theo cài thư viện node_modules

npm i

- Tiếp theo cài thêm nodemon để giám sát chỉnh sửa file, mỗi khi sửa file sẽ tự khởi động lại server

npm install -g nodemon

- Tiếp theo chạy lệnh: 

nodemon npm start

Ở bước này có thể xảy ra lỗi có liên quan chữ "Policy", bạn cần đọc kỹ thông báo lỗi. Lỗi này do VS Code không được cấp quyền thực thi JS ở bên ngoài. Bạn xem cách sửa ở bài viết này https://zezo.dev/view/hoc-nodejs-nhu-the-nao 

- Tiếp theo chạy xong bạn mở trình duyệt web nhập vào địa chỉ:  http://localhost:3000, nếu nhìn thấy nội dung có tiêu đề Express là thành công.

 

Bước 2: Cài thư viện mongoose để kết nối CSDL mongo từ nodejs

https://mongoosejs.com/docs/ 

Công việc cài đặt rất đơn giản

npm install mongoose --save

Bước 3: Tạo cấu trúc MVC

Bạn nên tạo thói quen tạo cấu trúc MVC cho ứng dụng để phát triển code

Api_Zezo_Dev/
            controllers
            models
            views   <-- thư mục này mặc định đã có, nhưng không cần dùng đến vì viết API sẽ không cần view.
            ....    <-- các thư mục khác theo mặc định như public, routes, middlewares....

Bước 4: Tạo model

- Trong thư mục model, bạn tạo file kết nối CSDL là db.js

const mongoose = require('mongoose');
mongoose.connect( 'mongodb://127.0.0.1:27017/demo_api_zezo_dev')
       .catch( (err) =>{
               console.log("Loi ket noi CSDL");
               console.log(err);
       });
      
module.exports = {mongoose}

- Tiếp theo bạn tạo file todoModel.js. Bài viết này demo với 2 trường dữ liệu title và status

 

const {mongoose} = require('./db');
const todoSchema = new mongoose.Schema(
    {
        title:{type:String, required: true},
        status:{type:Number, required: true, default: 0}
    },
    {
        collection: 'todos'  // đặt tên cho collection
    }
);
let todoModel = mongoose.model('todoModel', todoSchema);
module.exports = {todoModel}

 

Bước 5: Tạo cấu trúc hàm trong controller

Trong thư mục controllers, bạn tạo một file là todoController.js

 

const { todoModel } = require('../models/todoModel');
  
exports.getList = async (req, res, next) => {
	// lát nữa viết code chi tiết cho hàm sau
});

Bước 6: Tạo route

- Trong thư mục routes, bạn tạo file api.js

var express = require('express');
var router = express.Router();
var todoCtrl = require('../controllers/todoController');
// lấy danh sách todo, link GET http://localhost:3000/api/todos 
router.get('/todos', todoCtrl.getList );
module.exports = router;

- Tiếp theo bạn vào file app.js khai báo nhúng file api và khai báo route

var apiRouter = require('./routes/api');
app.use('/api', apiRouter);

Bước 7: Viết chi tiết cho hàm trong controller

exports.getList = async (req, res, next) => {
    let limit = 3; // số bản ghi trên 1 trang, cái này server tự quy định
    // khai báo một đối tượng dùng để cài dữ liệu trả về client theo một format nhất định
    let dataRes = {
        msg:'',
        status:0,
        data:[],
        totalPages:0,
        currentPage: 1, // mặc định là trang 1
        totalItems: 0
    };
    try {
    	// nếu có truyền vào địa chỉ một tham số là page thì gán nó vào currentPage
        if(typeof(req.query.page) != 'undefined' && !isNaN(req.query.page)){
            dataRes.currentPage = req.query.page;
        }
        // đếm tổng số bản ghi hợp lệ trong collection
        let totalItems = await todoModel.countDocuments();
        // tính ra tổng số trang, mỗi trang có số lượng bản ghi là giá trị của biến limit
        let totalPages = Math.ceil(totalItems / limit);
        // tính số bản ghi sẽ bỏ qua, ví dụ: mỗi trang 3 bản ghi, thì khi người dùng vào trang 2, sẽ phải bỏ qua 3 bản ghi đầu, lấy dữ liệu từ bản ghi thứ 4 đến hết số lượng giới hạn bản ghi limit.
        const skip = (dataRes.currentPage - 1) * limit; // Số lượng bản ghi cần bỏ qua
        // thực thi lệnh lấy dữ liệu
        let list = await todoModel.find()
                        .skip(skip)
                        .limit(limit);
        // gắn dữ liệu vào đối tượng res cho đúng format
        dataRes.status = 1;
        dataRes.msg ='Lấy danh sách thành công';
        dataRes.data = list;
        dataRes.totalPages =  totalPages;
        dataRes.totalItems = totalItems;
 
        res.status(200).json(dataRes);
    } catch (error) {
        dataRes.msg = error.message; 
        res.status(400).json(dataRes);
    }
}

Bước 8: Thử nghiệm ứng dụng

Bạn đã chạy lệnh nodemon ở trên thì không cần chạy lại npm start nữa.

 

Bạn có thể truy cập link api bằng trình duyệt web hoặc postman. Kết quả chạy lần đàu bạn sẽ thấy:

 http://:3000/api/todos?page=1

{
    "msg": "Lấy danh sách thành công",
    "status": 1,
    "data": [],
    "totalPages": 0,
    "currentPage": 1,
    "totalItems": 0
}

Giờ chưa có chức năng thêm, bạn hãy vào phần mềm Compass để nhập thủ công vào collection todos khoảng 10 bản ghi.

Tiếp theo bạn quay lại postman hoặc trình duyệt web bạn truy cập lại link api để xem kết quả trả về danh sách, bạn sẽ thấy phần data có 3 bản ghi, totalItems có 10 bản ghi ==> trong code đã giới hạn limit là 3 bản ghi trên 1 trang. Khi sử dụng bạn cần truyền thêm tham số page=x để biết sẽ truy cập vào trang thứ bao nhiêu. Bạn hãy thử thay đổi page=2 hoặc 3 hoặc 4 để xem kết quả.

Với page=4 link truy cập GET: http://:3000/api/todos?page=4   sẽ có kết quả:

{
    "msg": "Lấy danh sách thành công",
    "status": 1,
    "data": [
        {
            "_id": "6616ae38d3fb462b1a9528e9",
            "title": "Việc số 10",
            "status": 1
        }
    ],
    "totalPages": 4,
    "currentPage": "4",
    "totalItems": 10
}

 

Nguồn: zezo.dev