Menu
CoddyTech

Projeção, ordenação e limite

Parte da seção Bancos de dados com MongoDB do Journey de Node.js da Coddy. Lição 13 de 29.

Uma lista dos “livros mais recentes” precisa de alguns campos de alguns livros, em ordem.

Uma projeção seleciona os campos que uma consulta retorna: 1 mantém um campo, e _id vem junto, a menos que você defina como 0. No cursor, sort({ field: -1 }) ordena do maior para o menor (1 é do menor para o maior), e limit(n) mantém os primeiros n resultados.

// as 5 maiores pontuações, apenas nome e pontuação
await players
    .find({}, { projection: { name: 1, score: 1, _id: 0 } })
    .sort({ score: -1 })
    .limit(5)
    .toArray();

O banco de dados ordena antes de limitar, independentemente da ordem em que você encadeia as duas chamadas. Ordenar o array em JavaScript depois de limit significa ordenar os cinco resultados errados.

challenge icon

Desafio

Fácil

Esta etapa abre o projeto de API de estante preparado do curso, em vez dos arquivos do seu projeto de Filtros de consulta (incluindo server.js). Seu trabalho anterior continua na própria lição. Leia os arquivos fornecidos antes de editar server.js. Esta cópia contém as rotas da estante e o filtro por intervalo de anos.

A página inicial mostra os livros mais recentes, apenas com o título e o ano.

  1. Em server.js, adicione uma rota GET /books/newest. Coloque-a acima de GET /books/:id. O Express tenta as rotas na ordem, e /books/:id também corresponde a /books/newest. Ele trataria newest como um id e responderia com 400.
  2. A rota retorna os livros ordenados por year, do maior para o menor.
  3. ?n= indica quantos livros retornar. Quando n estiver ausente, retorne 3.
  4. Cada livro contém apenas title e year, sem _id e sem nenhum outro campo. Deixe a consulta escolher os campos, ordenar os livros e limitar a lista. Para os livros iniciais, GET /books/newest?n=2 retorna:
    [ { "title": "Kindred", "year": 1979 }, { "title": "Dune", "year": 1965 } ]
    Experimente: Envie GET /books/newest. Você recebe Kindred (1979), Dune (1965) e Emma (1815), nessa ordem, cada um com apenas um título e um ano. Envie GET /books/newest?n=1: você recebe [ { "title": "Kindred", "year": 1979 } ]. Se receber 400, GET /books/:id recebeu a solicitação, então mova sua rota para cima dela.

Experimente você mesmo

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());

// Todo erro retorna { 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 filter = {};
    if (req.query.author) {
        filter.author = req.query.author;
    }
    if (req.query.from || req.query.to) {
        filter.year = {};
        if (req.query.from) {
            filter.year.$gte = Number(req.query.from);
        }
        if (req.query.to) {
            filter.year.$lte = Number(req.query.to);
        }
    }
    const list = await books.find(filter).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');
});
quiz iconTeste seus conhecimentos

Esta lição inclui um quiz rápido. Comece a lição para respondê-lo e acompanhar seu progresso.

Todas as lições de Bancos de dados com MongoDB

Pratique por conta própria: Playground de Express