Menu
CoddyTech

Bộ lọc truy vấn

Thuộc phần Cơ sở dữ liệu với MongoDB trong hành trình Node.js của Coddy. Bài học 9 trên 29.

Khách hàng thường chỉ muốn lấy một số sách, và cơ sở dữ liệu có thể tự chọn giúp.

Đối tượng bạn truyền vào find là một bộ lọc: một tài liệu khớp khi mọi trường trong bộ lọc đều khớp. Giá trị thông thường có nghĩa là bằng nhau. Toán tử là một khóa bắt đầu bằng $ và dùng để so sánh: $gte có nghĩa là lớn hơn hoặc bằng, $lte có nghĩa là nhỏ hơn hoặc bằng. Hai toán tử trên cùng một trường dùng chung một đối tượng: { total: { $gte: 20, $lte: 50 } } giữ lại các tổng từ 20 đến 50.

// Đơn hàng đã thanh toán có tổng giá trị từ 20 trở lên
await orders.find({ status: 'paid', total: { $gte: 20 } }).toArray();

Kiểu dữ liệu rất quan trọng: { $gte: '20' } so sánh một chuỗi, còn MongoDB không bao giờ so khớp chuỗi với trường số. Mọi thứ trong req.query đều là chuỗi, vì vậy hãy chuyển số thành kiểu số bằng Number() trước khi đưa chúng vào bộ lọc.

challenge icon

Thử thách

Dễ

Bước này mở dự án API kệ sách đã chuẩn bị sẵn cho khóa học, thay vì các tệp dự án của bạn trong Finding by ObjectId (bao gồm server.js). Phần bạn đã làm trước đó vẫn nằm trong bài học riêng. Hãy đọc các tệp được cung cấp trước khi chỉnh sửa server.js. Bản sao này có các tuyến thêm sách vào cơ sở dữ liệu và tìm kiếm bằng ObjectId.

Ứng dụng khách chỉ cần một số sách: sách của một tác giả, hoặc sách xuất bản trong một số năm nhất định. Hãy để cơ sở dữ liệu chọn chúng.

  1. Trong server.js, hãy thay đổi tuyến GET /books. Tạo một đối tượng bộ lọc từ chuỗi truy vấn rồi truyền nó vào find. Tuyến này vẫn trả về một mảng sách dạng JSON.
  2. ?author=Jane%20Austen chỉ trả về những cuốn sách có author chính xác là Jane Austen. (%20 là cách URL viết dấu cách.)
  3. ?from=1960 trả về những cuốn sách có year từ năm 1960 trở đi. ?to=1980 trả về những cuốn sách từ năm 1980 trở về trước. Nếu dùng cả hai, năm xuất bản của sách phải nằm trong khoảng giữa hai năm, và tính cả hai năm đó. Có thể chỉ dùng một trong hai tham số.
  4. Giá trị truy vấn luôn được gửi đến dưới dạng chuỗi, nhưng năm lưu trong cơ sở dữ liệu là số. Hãy chuyển from và to thành số trước khi đưa chúng vào bộ lọc, nếu không sẽ không có kết quả nào khớp.
  5. Nếu không có truy vấn, tuyến này trả về tất cả sách như trước. Thử nhé: Gửi GET /books?from=1960&to=1980: bạn nhận được Dune (1965) và Kindred (1979). Gửi GET /books?from=1970: bạn chỉ nhận được Kindred. Gửi GET /books?to=1900: bạn chỉ nhận được Emma (1815). Gửi GET /books?author=Jane%20Austen: bạn chỉ nhận được Emma. Gửi GET /books: bạn nhận được cả ba cuốn.

Tự làm thử

import express from 'express';
import { MongoClient, ObjectId } from 'mongodb';

const client = new MongoClient('mongodb://localhost:27017');
const db = client.db('shelf');
const books = db.collection('books');

await books.insertMany([
    { title: 'Dune', author: 'Frank Herbert', year: 1965, isbn: '9780441013593', genre: 'scifi' },
    { title: 'Kindred', author: 'Octavia E. Butler', year: 1979, isbn: '9780807083697', genre: 'scifi' },
    { title: 'Emma', author: 'Jane Austen', year: 1815, isbn: '9780141439587', genre: 'classic' },
]);

const app = express();
app.use(express.json());

// Mọi lỗi đều trả về { error: message }.
function sendError(res, status, message) {
    res.status(status).json({ error: message });
}

app.get('/', (req, res) => {
    res.send('Bookshelf API');
});

app.get('/books', async (req, res) => {
    const list = await books.find().toArray();
    res.json(list);
});

app.post('/books', async (req, res) => {
    const book = req.body;
    await books.insertOne(book);
    res.status(201).json(book);
});

app.get('/books/:id', async (req, res) => {
    if (!ObjectId.isValid(req.params.id)) {
        return sendError(res, 400, 'Not a valid id');
    }
    const book = await books.findOne({ _id: new ObjectId(req.params.id) });
    if (!book) {
        return sendError(res, 404, 'No such book');
    }
    res.json(book);
});

app.listen(3000, () => {
    console.log('Bookshelf is running on port 3000');
});

Tất cả bài học trong Cơ sở dữ liệu với MongoDB

Tự luyện tập: Playground Express