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

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ùngparseFloatvàisNaNđể đảm bảoprice_maxlà 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ặccamelCase(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.querytiệ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ùngreq.bodyvớ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áiq=req.query+nodejschí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.queryvì 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.bodytrong 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.bodyvớ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(ở đây123làreq.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é!