Menu
CoddyTech

Projection, tri et limite

Fait partie de la section Bases de données avec MongoDB du Journey Node.js de Coddy. Leçon 13 sur 29.

Une liste des « livres les plus récents » a besoin de quelques champs provenant de quelques livres, dans l’ordre.

Une projection sélectionne les champs auxquels répond une requête : 1 conserve un champ, et _id est inclus sauf si tu le définis sur 0. Sur le curseur, sort({ field: -1 }) trie du plus grand au plus petit (1 trie du plus petit au plus grand), et limit(n) conserve les n premiers résultats.

// les 5 meilleurs scores, uniquement name et score
await players
    .find({}, { projection: { name: 1, score: 1, _id: 0 } })
    .sort({ score: -1 })
    .limit(5)
    .toArray();

La base de données effectue le tri avant la limitation, quel que soit l’ordre dans lequel tu enchaînes les deux appels. Trier le tableau en JavaScript après limit revient à trier les cinq mauvais résultats.

challenge icon

Défi

Facile

Cette étape ouvre le projet d’API bookshelf préparé pour le cours, plutôt que les fichiers de ton projet de Query Filters (y compris server.js). Ton travail précédent reste dans sa propre leçon. Lis les fichiers fournis avant de modifier server.js. Cette copie contient les routes de la bibliothèque et le filtre par plage d’années.

La page d’accueil affiche les livres les plus récents, avec seulement leur titre et leur année.

  1. Dans server.js, ajoute une route GET /books/newest. Place-la au-dessus de GET /books/:id. Express essaie les routes dans l’ordre, et /books/:id correspond aussi à /books/newest. La route interpréterait newest comme un identifiant et répondrait avec le code 400.
  2. La route renvoie les livres triés par year, du plus élevé au plus bas.
  3. ?n= indique le nombre de livres à renvoyer. Si n est absent, renvoie 3.
  4. Chaque livre ne contient que title et year, sans _id ni aucun autre champ. Laisse la requête choisir les champs, trier les livres et réduire la liste. Pour les livres de départ, GET /books/newest?n=2 renvoie :
    [ { "title": "Kindred", "year": 1979 }, { "title": "Dune", "year": 1965 } ]
    Essaie : Envoie GET /books/newest. Tu obtiens Kindred (1979), Dune (1965) et Emma (1815), dans cet ordre, chacun avec seulement un titre et une année. Envoie GET /books/newest?n=1 : tu obtiens [ { "title": "Kindred", "year": 1979 } ]. Si tu obtiens le code 400, c’est GET /books/:id qui a traité la requête ; déplace donc ta route au-dessus.

Essayez vous-même

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

// Chaque erreur renvoie { 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 iconTestez-vous

Cette leçon comprend un petit quiz. Commencez la leçon pour y répondre et suivre votre progression.

Toutes les leçons de Bases de données avec MongoDB

Entraînez-vous par vous-même : Playground Express