0

[Series Thực Chiến E-commerce] Bài 34: Đọc bài viết & Thuật toán "Câu View" - Lấy chi tiết Blog (Get Blog By ID)

Chào bố đời! Anh em mình lại tiếp tục phá đảo hệ thống E-commerce nào.

Ở Bài 33, chúng ta đã bày toàn bộ bài viết ra trang chủ rồi. Bây giờ, đóng vai một độc giả, khi thấy tiêu đề "5 mẹo chọn mua Laptop năm nay" quá hấp dẫn, họ sẽ click vào để xem chi tiết. Đó chính là lúc API Get Blog By ID của chúng ta được gọi.

Đoạn code bố đời chuẩn bị cơ bản là chạy tốt, bắt lỗi 404 cực kỳ chuẩn xác. NHƯNG ở góc độ thực chiến, nếu chỉ dùng findById thì chúng ta đang bỏ lỡ một tính năng cực kỳ quan trọng của mọi hệ thống Blog: Đếm lượt xem (View Count).

Cùng mình nâng cấp đoạn code này lên tầm cao mới nhé!

1. Phẫu thuật Controller: Tuyệt chiêu "Câu View" bằng $inc

Thay vì chỉ lấy dữ liệu ra một cách thụ động, chúng ta hãy tư duy thế này: Mỗi lần API Get Blog By ID được gọi thành công, đồng nghĩa với việc có 1 người vừa click vào đọc bài. Vậy tại sao mình không kết hợp luôn việc +1 vào tổng số lượt xem (numberViews) của bài viết đó nhỉ?

Mongoose hỗ trợ một toán tử cực kỳ lợi hại để làm việc này là $inc (Increment). Anh em mở file controllers/blog.js và "độ" lại hàm này như sau:

// Lấy thông tin chi tiết 1 bài blog (Kèm tính năng tăng View)
const getBlogById = asyncHandler(async (req, res) => {
  // Thống nhất dùng 'bid' (Blog ID) cho đồng bộ với Bài 32 nhé bố đời!
  const { bid } = req.params; 

  // 💡 GÓC NHÌN THỰC CHIẾN: Vừa tìm kiếm, vừa tăng lượt xem lên 1
  // Dùng findByIdAndUpdate thay vì findById
  const blog = await Blog.findByIdAndUpdate(
      bid, 
      { $inc: { numberViews: 1 } }, // Toán tử $inc giúp cộng thêm 1 vào trường numberViews
      { new: true } // Trả về data mới nhất sau khi đã cộng view
  )
  // 💡 Tip mở rộng: Thường ở đây mình sẽ dùng thêm .populate() để lấy tên người Like/Dislike
  // .populate('likes', 'firstname lastname')
  // .populate('dislikes', 'firstname lastname');

  if (!blog) {
    return res.status(404).json({ success: false, message: 'Blog not found - Bài viết không tồn tại' });
  }

  return res.status(200).json({
    success: true,
    blog
  });
});

module.exports = {
  createBlog,
  updateBlog,
  getAllBlogs,
  getBlogById, // Xuất xưởng
};

Chỉ với một thay đổi nhỏ, bài viết của chúng ta giờ đây đã biết "nhảy số" mỗi khi có người đọc. Quá xịn xò!

2. Gỡ bỏ Trạm gác (Router): Lại là sự tích cái cổng sắt

Bố đời nhìn lại đoạn code Router vừa ném cho mình xem: router.get('/blogs/:id', [verifyAccessToken, isAdmin], ctrls.getBlogById);

Trời đất ơi, làm tính năng cho khách vào đọc bài mà bố đời lại dựng cái cổng sắt chà bá [verifyAccessToken, isAdmin] chặn ngay cửa thế này! 😂 Độc giả đang hứng thú click vào đọc tin tức mà web hiện lên dòng chữ "Yêu cầu quyền Admin", chắc họ thót tim thoát trang luôn mất.

Cũng giống như Bài 33, hành động Xem chi tiết Blog là Public. Mình phải mở toang cửa đón khách nhé. Đồng thời mình đổi lại :id thành :bid cho khớp với Controller.

Anh em vào file routers/blog.js dọn dẹp lại xíu:

const router = require('express').Router();
const ctrls = require('../controllers/blog');
const { verifyAccessToken, isAdmin } = require('../middlewares/verifyToken');

router.post('/blogs', [verifyAccessToken, isAdmin],  ctrls.createBlog);
router.put('/blogs/:bid', [verifyAccessToken, isAdmin],  ctrls.updateBlog);

// GET: Lấy danh sách (PUBLIC)
router.get('/blogs', ctrls.getAllBlogs);

// 💡 GET: Lấy chi tiết 1 bài viết -> Tháo cổng sắt ra cho khách vào!
router.get('/blogs/:bid', ctrls.getBlogById);

module.exports = router;

Lời kết

Test thử ngay cho nóng! Bố đời mở Postman, chọn GET nã thẳng vào http://localhost:5000/api/blog/blogs/<id-bài-viết>. Gửi 1 lần thấy numberViews lên 1. Gửi thêm lần nữa thấy nó nhảy lên 2. Cảm giác code nhảy số tự động nó "phê" lắm đúng không?

Đọc bài xong thấy hay quá, độc giả muốn Thả tim (Like) để ủng hộ tác giả. Hoặc thấy dở quá thì Dislike. Đây là lúc chúng ta chạm trán với một trong những logic "khoai" nhất của mảng Blog: Lession 35: Like Blogs.

Logic phần này khá lắt léo (Kiểm tra xem User đã dislike chưa? Nếu rồi thì bỏ dislike chuyển sang like. Nếu đang like rồi mà bấm phát nữa thì thành bỏ like...).


All rights reserved

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