req.query: Cảnh Sát Giao Thông Của URL, GenZ Ơi!
Nodejs

req.query: Cảnh Sát Giao Thông Của URL, GenZ Ơi!

Author

Admin System

@root

Ngày xuất bản

23 Mar, 2026

Lượt xem

1 Lượt

"req.query"

Chào các "thánh code" GenZ của anh Creyt! Hôm nay, chúng ta sẽ "đập hộp" một khái niệm nghe thì có vẻ "hàn lâm" nhưng thực ra lại "cool ngầu" và cực kỳ thiết yếu trong thế giới backend Node.js: req.query. Nghe quen mà lạ đúng không? Đừng lo, anh Creyt sẽ "giải mã" nó theo cách dễ hiểu nhất, đảm bảo "nuốt trôi" liền!

1. req.query là gì mà "hot" thế?

Để dễ hình dung, các em cứ tưởng tượng thế này: Một cái URL (Uniform Resource Locator) giống như một cái địa chỉ nhà trên đường cao tốc Internet vậy. Ví dụ, https://shopee.vn/search?keyword=ao+thun&category=123&minPrice=50000&maxPrice=100000.

  • Cái phần https://shopee.vn/search là con đường chính, là địa chỉ mà các em muốn tới.
  • Còn cái phần sau dấu chấm hỏi ? ấy, chính là "tờ giấy note" mà các em dán lên gói hàng trước khi gửi đi. Nó ghi những yêu cầu đặc biệt, những thông tin phụ trợ mà các em muốn người nhận (server) biết để xử lý gói hàng (request) của mình tốt hơn.

req.query chính là cái "hộp" chứa tất cả những "tờ giấy note" đó! Trong Node.js (cụ thể là với framework Express.js), khi một request HTTP đến server của bạn, req.query là một đối tượng (object) mà Express tự động phân tích và điền vào. Nó chứa các cặp key-value lấy từ chuỗi truy vấn (query string) của URL.

Ví dụ: Với URL http://localhost:3000/api/products?category=Thời%20trang&price_max=300000

Thì req.query trong code của bạn sẽ trông như thế này:

{
  category: 'Thời trang',
  price_max: '300000'
}

Dễ hiểu không? Nó là cách client (trình duyệt, ứng dụng di động) "thì thầm" những yêu cầu tùy chọn cho server mà không làm thay đổi cái địa chỉ chính của tài nguyên.

2. Dùng req.query để làm gì?

"Tờ giấy note" này có "phép thuật" ghê gớm lắm đó, GenZ ạ! Nó thường được dùng cho các trường hợp:

  • Lọc dữ liệu (Filtering): Muốn xem tất cả sản phẩm thuộc danh mục "Điện thoại"? ?category=dien_thoai.
  • Sắp xếp dữ liệu (Sorting): Muốn sắp xếp bài viết theo ngày mới nhất hay lượt xem cao nhất? ?sort_by=date_desc.
  • Phân trang (Pagination): Muốn lấy trang thứ 2, mỗi trang 10 mục? ?page=2&limit=10.
  • Tìm kiếm (Searching): Tìm kiếm sản phẩm có tên "áo thun"? ?search=ao+thun.
  • Tham số tùy chọn (Optional parameters): Đôi khi bạn muốn server trả về dữ liệu theo một định dạng nhất định, hoặc hiển thị một ngôn ngữ khác. ?lang=en.

Nói chung, bất cứ khi nào bạn cần truyền các tham số tùy chọn, không ảnh hưởng đến việc định danh tài nguyên chính, và không quá nhạy cảm (vì nó hiện rõ trên URL), thì req.query chính là "người hùng" của bạn.

3. Code Ví Dụ Minh Họa (Chất Lượng Cao)

Anh Creyt sẽ dựng một server Express "mini" để các em thấy req.query hoạt động như thế nào trong việc lọc và sắp xếp danh sách sản phẩm nhé!

const express = require('express');
const app = express();
const PORT = 3000;

// Một "database" nhỏ xíu để minh họa
const products = [
    { id: 1, name: 'Áo thun GenZ', category: 'Thời trang', price: 199000, color: 'đen' },
    { id: 2, name: 'Quần jean rách', category: 'Thời trang', price: 350000, color: 'xanh' },
    { id: 3, name: 'Tai nghe Bluetooth', category: 'Phụ kiện', price: 800000, color: 'trắng' },
    { id: 4, name: 'Sạc dự phòng 10000mAh', category: 'Phụ kiện', price: 250000, color: 'đen' },
    { id: 5, name: 'Sách "Lập trình siêu ngầu"', category: 'Sách', price: 120000, color: 'nhiều màu' },
    { id: 6, name: 'Balo laptop gaming', category: 'Phụ kiện', price: 700000, color: 'đen' }
];

// Route để lấy danh sách sản phẩm với các tùy chọn lọc/sắp xếp từ req.query
app.get('/api/products', (req, res) => {
    console.log('Các yêu cầu đặc biệt từ GenZ (req.query):', req.query); 

    let filteredProducts = [...products]; // Tạo bản sao để lọc, tránh làm thay đổi dữ liệu gốc

    const { category, price_max, sort_by, search } = req.query; // Bóc tách các tham số từ req.query

    // 1. Lọc theo category (danh mục)
    if (category) {
        filteredProducts = filteredProducts.filter(p =>
            p.category.toLowerCase() === category.toLowerCase()
        );
    }

    // 2. Lọc theo giá tối đa
    if (price_max) {
        const maxPrice = parseFloat(price_max); // Chuyển đổi từ string sang số thực
        if (!isNaN(maxPrice)) { // Đảm bảo đây là một số hợp lệ
            filteredProducts = filteredProducts.filter(p => p.price <= maxPrice);
        } else {
            return res.status(400).json({ message: 'Giá tối đa không hợp lệ, GenZ ơi!' });
        }
    }

    // 3. Tìm kiếm theo tên sản phẩm
    if (search) {
        filteredProducts = filteredProducts.filter(p =>
            p.name.toLowerCase().includes(search.toLowerCase())
        );
    }

    // 4. Sắp xếp
    if (sort_by) {
        switch (sort_by) {
            case 'price_asc': // Giá tăng dần
                filteredProducts.sort((a, b) => a.price - b.price);
                break;
            case 'price_desc': // Giá giảm dần
                filteredProducts.sort((a, b) => b.price - a.price);
                break;
            case 'name_asc': // Tên tăng dần (theo alphabet)
                filteredProducts.sort((a, b) => a.name.localeCompare(b.name));
                break;
            default:
                // Có thể bỏ qua hoặc trả về lỗi nếu sort_by không hợp lệ
                break;
        }
    }

    // Nếu không tìm thấy sản phẩm nào
    if (filteredProducts.length === 0) {
        return res.status(404).json({ message: 'Không tìm thấy sản phẩm nào theo yêu cầu của bạn, GenZ ạ!' });
    }

    res.json({
        message: 'Đây là danh sách sản phẩm theo yêu cầu đặc biệt của bạn:',
        count: filteredProducts.length,
        data: filteredProducts
    });
});

app.listen(PORT, () => {
    console.log(`Server của Creyt đang chạy ở http://localhost:${PORT}`);
    console.log('Thử nghiệm với các URL sau:');
    console.log(`- Lấy tất cả sản phẩm: http://localhost:${PORT}/api/products`);
    console.log(`- Lọc theo category "Thời trang": http://localhost:${PORT}/api/products?category=Thời%20trang`);
    console.log(`- Lọc theo giá tối đa 300k: http://localhost:${PORT}/api/products?price_max=300000`);
    console.log(`- Lọc theo category và giá: http://localhost:${PORT}/api/products?category=Thời%20trang&price_max=200000`);
    console.log(`- Tìm kiếm "thun" và sắp xếp giá tăng dần: http://localhost:${PORT}/api/products?search=thun&sort_by=price_asc`);
    console.log(`- Lọc phụ kiện và sắp xếp giá giảm dần: http://localhost:${PORT}/api/products?category=Phụ%20kiện&sort_by=price_desc`);
});

Cách chạy:

  1. Lưu đoạn code trên vào một file app.js.
  2. Mở Terminal/CMD, chạy npm init -y (nếu chưa có package.json).
  3. Cài Express: npm install express.
  4. Chạy server: node app.js.
  5. Mở trình duyệt và thử các URL mà anh Creyt đã gợi ý trong console.log.
Illustration

4. Mẹo (Best Practices) của Creyt để "cân" req.query

Là một "giảng viên lập trình lão luyện" như anh Creyt, anh đã "ăn hành" đủ nhiều để đúc kết ra vài mẹo xương máu cho các em đây:

  • "Đừng tin ai cả!" (Validate và Sanitize): Đây là điều quan trọng nhất! Dữ liệu từ req.query (hay bất kỳ input nào từ người dùng) luôn phải được kiểm tra (validate) và làm sạch (sanitize) trước khi sử dụng. Như trong ví dụ, anh đã dùng parseFloatisNaN để đảm bảo price_max là một số hợp lệ. Nếu không, hacker có thể gửi những chuỗi quái dị để làm sập server hoặc thậm chí là tấn công SQL Injection (nếu bạn dùng trực tiếp vào database query).
  • Giá trị mặc định (Default Values): Client không phải lúc nào cũng gửi đủ các tham số. Hãy cung cấp giá trị mặc định cho các tham số tùy chọn. Ví dụ: const page = parseInt(req.query.page) || 1; (mặc định trang 1).
  • Nhất quán tên (Consistent Naming): Dùng snake_case (price_max) hoặc camelCase (priceMax) một cách nhất quán cho tên các query parameter để dễ đọc và dễ quản lý hơn.
  • Giới hạn độ dài URL: Mặc dù req.query tiện lợi, nhưng URL có giới hạn độ dài nhất định (thường là vài nghìn ký tự tùy trình duyệt/server). Đừng cố nhồi nhét quá nhiều dữ liệu vào đây. Nếu dữ liệu quá lớn hoặc nhạy cảm, hãy dùng req.body với các request POST/PUT.
  • Sử dụng thư viện hỗ trợ: Đối với các ứng dụng phức tạp, có nhiều thư viện giúp validate và sanitize dữ liệu hiệu quả hơn, ví dụ express-validator.

5. Ứng dụng thực tế: req.query "làm mưa làm gió" ở đâu?

Chắc chắn các em đã dùng req.query hàng ngày mà không biết đấy thôi:

  • Google Search: Khi các em gõ "req.query nodejs" vào Google, URL sẽ thành https://www.google.com/search?q=req.query+nodejs. Cái q=req.query+nodejs chính là req.query đó!
  • Các trang thương mại điện tử (Shopee, Tiki, Lazada): Khi các em lọc sản phẩm theo giá, màu sắc, danh mục, sắp xếp theo lượt bán chạy, hay chuyển trang, tất cả đều dùng req.query. Ví dụ: https://shopee.vn/search?keyword=áo%20thun&category=123&minPrice=50000&maxPrice=100000&sortBy=sales.
  • YouTube/Netflix/Spotify: Lọc video theo thể loại, sắp xếp kết quả tìm kiếm, hay thậm chí là các tham số định dạng video/audio đều có thể dùng query string.
  • API của các ứng dụng di động: Các ứng dụng mobile thường gọi API backend với các tham số phân trang, lọc dữ liệu tương tự như web.

6. Thử nghiệm của Creyt và lời khuyên nên dùng cho case nào

Anh Creyt đã từng "đau đầu" với req.query khi xây dựng một hệ thống quản lý tin tức phức tạp. Người dùng có thể lọc bài viết theo hàng chục tiêu chí khác nhau: tác giả, chủ đề, ngày đăng, trạng thái duyệt, độ dài bài viết, v.v. req.query đã giúp anh xử lý linh hoạt mọi yêu cầu đó. Tuy nhiên, nếu không cẩn thận validate, server có thể gặp lỗi hoặc trả về dữ liệu không mong muốn.

Khi nào nên "triệu hồi" req.query?

  • GET requests: Đây là "sân chơi" chính của req.query vì nó dùng để yêu cầu dữ liệu từ server và các tham số là để lọc, sắp xếp, phân trang dữ liệu đó.
  • Tham số không nhạy cảm: Bất cứ dữ liệu nào mà việc hiển thị trên URL không gây rủi ro bảo mật (ví dụ: filter category, page number).
  • Tính cacheable (có thể lưu cache): Các request với query string khác nhau có thể được các proxy server hoặc trình duyệt cache riêng biệt, giúp tăng tốc độ tải trang cho các request lặp lại.

Khi nào nên "né" req.query?

  • Dữ liệu nhạy cảm: Tuyệt đối không bao giờ truyền mật khẩu, token xác thực, hoặc bất kỳ thông tin cá nhân nhạy cảm nào qua query string. Nó sẽ hiển thị rõ ràng trong lịch sử duyệt web và log server, dễ bị lộ. Thay vào đó, dùng req.body trong POST request hoặc header.
  • Dữ liệu lớn: Nếu bạn cần gửi một lượng lớn dữ liệu (ví dụ: nội dung bài viết dài), URL không phải là nơi lý tưởng. Dùng req.body với method POST/PUT.
  • Tham số bắt buộc và định danh tài nguyên: Nếu tham số đó là một phần của việc định danh tài nguyên (ví dụ: ID của một user), hãy dùng req.params. Ví dụ: /users/123 (ở đây 123req.params.id), chứ không phải /users?id=123.

Kết luận

Vậy đó, GenZ! req.query không chỉ là một khái niệm khô khan mà nó là một "công cụ quyền năng" giúp bạn "thì thầm" những yêu cầu đặc biệt đến server, tạo ra những ứng dụng web linh hoạt và thông minh. Nắm vững nó, bạn sẽ "cân" được rất nhiều kịch bản phức tạp trong phát triển backend. Hãy thực hành thật nhiều để "hack" được trải nghiệm người dùng một cách hiệu quả nhất nhé! Có gì thắc mắc, cứ "bắn" câu hỏi cho anh Creyt!

Thuộc Series: Nodejs

Bài giảng này được tự động xuất bản ngẫu nhiên từ thư viện kiến thức. Đừng quên đón xem các Từ khoá Hướng Dẫn tiếp theo nhé!

#tech #cyberpunk #laravel
Chỉnh sửa bài viết

Bình luận (0)

Vui lòng Đăng Nhập để Bình luận

Hỗ trợ Markdown cơ bản
Nguyễn Văn A
1 ngày trước

Tính năng này đỉnh quá ad ơi, chờ mãi mới thấy một blog Tiếng Việt có UI/UX xịn như vầy!