Menu
CoddyTech

Projektion, Sortierung und Limit

Teil des Abschnitts Datenbanken mit MongoDB der Node.js-Journey von Coddy. Lektion 13 von 29.

Eine Liste der „neuesten Bücher“ benötigt einige Felder aus einigen Büchern, in einer bestimmten Reihenfolge.

Eine Projektion wählt die Felder aus, die eine Abfrage zurückgibt: 1 behält ein Feld bei, und _id wird mitgeliefert, sofern du es nicht auf 0 setzt. Auf dem Cursor sortiert sort({ field: -1 }) von hoch nach niedrig (1 sortiert von niedrig nach hoch), und limit(n) behält die ersten n Ergebnisse bei.

// die 5 höchsten Punktzahlen, nur name und score
await players
    .find({}, { projection: { name: 1, score: 1, _id: 0 } })
    .sort({ score: -1 })
    .limit(5)
    .toArray();

Die Datenbank sortiert, bevor sie begrenzt, unabhängig davon, in welcher Reihenfolge du die beiden Aufrufe verkettest. Wenn du das Array in JavaScript nach limit sortierst, sortierst du die falschen fünf Ergebnisse.

challenge icon

Aufgabe

Einfach

Dieser Schritt öffnet das vorbereitete Bücherregal-API-Projekt des Kurses und nicht deine Projektdateien aus Abfragefilter (einschließlich server.js). Deine frühere Arbeit bleibt in ihrer eigenen Lektion. Lies die bereitgestellten Dateien, bevor du server.js bearbeitest. Diese Kopie enthält die Bücherregal-Routen und den Jahresbereichsfilter.

Die Startseite zeigt die neuesten Bücher, jeweils nur mit Titel und Jahr.

  1. Füge in server.js eine Route GET /books/newest hinzu. Setze sie oberhalb von GET /books/:id. Express probiert die Routen der Reihe nach aus, und /books/:id passt auch auf /books/newest. Dabei würde newest als ID behandelt und eine Antwort mit Status 400 gesendet.
  2. Die Route gibt Bücher zurück, sortiert nach year, beginnend mit dem höchsten Wert.
  3. ?n= gibt an, wie viele Bücher zurückgegeben werden sollen. Wenn n fehlt, gib 3 zurück.
  4. Jedes Buch enthält nur title und year, ohne _id und ohne weitere Felder. Lass die Abfrage die Felder auswählen, die Bücher sortieren und die Liste kürzen. Bei den Büchern im Starterprojekt gibt GET /books/newest?n=2 Folgendes zurück:
    [ { "title": "Kindred", "year": 1979 }, { "title": "Dune", "year": 1965 } ]
    Probiere es aus: Sende GET /books/newest. Du erhältst Kindred (1979), Dune (1965) und Emma (1815) in dieser Reihenfolge, jeweils nur mit Titel und Jahr. Sende GET /books/newest?n=1: Du erhältst [ { "title": "Kindred", "year": 1979 } ]. Wenn du den Status 400 erhältst, hat GET /books/:id die Anfrage übernommen. Verschiebe deine Route also darüber.

Probier es selbst

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

// Bei jedem Fehler lautet die Antwort { 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 dich selbst

Diese Lektion enthält ein kurzes Quiz. Starte die Lektion, um es zu beantworten und deinen Fortschritt zu speichern.

Alle Lektionen in Datenbanken mit MongoDB

Übe selbstständig: Express-Playground