Menu
CoddyTech

Proyección, ordenación y límite

Parte de la sección Bases de datos con MongoDB del Journey de Node.js de Coddy. Lección 13 de 29.

Una lista de los libros más recientes necesita algunos campos de algunos libros, en orden.

Una proyección selecciona los campos que devuelve una consulta: 1 conserva un campo, y _id se incluye a menos que lo establezcas en 0. En el cursor, sort({ field: -1 }) ordena de mayor a menor (1 ordena de menor a mayor), y limit(n) conserva los primeros n resultados.

// las 5 puntuaciones más altas, solo el nombre y la puntuación
await players
    .find({}, { projection: { name: 1, score: 1, _id: 0 } })
    .sort({ score: -1 })
    .limit(5)
    .toArray();

La base de datos ordena antes de limitar, sin importar en qué orden encadenes las dos llamadas. Ordenar el arreglo en JavaScript después de limit ordena los cinco resultados equivocados.

challenge icon

Desafío

Fácil

Este paso abre el proyecto de API de biblioteca preparado para el curso, en lugar de los archivos de tu proyecto de Filtros de consulta (incluido server.js). Tu trabajo anterior permanece en su propia lección. Lee los archivos proporcionados antes de editar server.js. Esta copia contiene las rutas de la biblioteca y el filtro por intervalo de años.

La página de inicio muestra los libros más recientes, solo con su título y año.

  1. En server.js, agrega una ruta GET /books/newest. Colócala encima de GET /books/:id. Express intenta las rutas en orden, y /books/:id también coincide con /books/newest. Interpretaría newest como un id y respondería con 400.
  2. La ruta devuelve los libros ordenados por year, de mayor a menor.
  3. ?n= indica cuántos libros devolver. Si n no está presente, devuelve 3.
  4. Cada libro contiene solo title y year, sin _id ni ningún otro campo. Deja que la consulta seleccione los campos, ordene los libros y recorte la lista. Para los libros iniciales, GET /books/newest?n=2 devuelve:
    [ { "title": "Kindred", "year": 1979 }, { "title": "Dune", "year": 1965 } ]
    Pruébalo: Envía GET /books/newest. Obtendrás Kindred (1979), Dune (1965) y Emma (1815), en ese orden, cada uno con solo un título y un año. Envía GET /books/newest?n=1: obtendrás [ { "title": "Kindred", "year": 1979 } ]. Si obtienes 400, GET /books/:id recibió la solicitud, así que mueve tu ruta encima de esa.

Pruébalo tú mismo

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

// Cada error devuelve { 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 iconPonte a prueba

Esta lección incluye un breve cuestionario. Empieza la lección para responderlo y registrar tu progreso.

Todas las lecciones de Bases de datos con MongoDB

Practica por tu cuenta: Playground de Express