Menu
CoddyTech

Dokumente aktualisieren

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

Wenn du das Jahr eines Buchs korrigierst, sollte sich nur dieses Feld ändern und alle anderen unverändert bleiben.

updateOne(filter, update) ändert das erste Dokument, auf das der Filter zutrifft. Das Update besteht aus Operatoren: $set schreibt die angegebenen Felder und behält alle anderen Felder bei. Ein einfaches Objekt ohne Operator wird mit „Update document requires atomic operators“ abgelehnt.

const result = await players.updateOne(
    { name: 'Ada' },
    { $set: { score: 120, level: 4 } }
);
result.matchedCount;  // 1, wenn ein Spieler gefunden wurde, 0, wenn keiner gefunden wurde
result.modifiedCount; // 0, wenn die Werte bereits gleich waren

Unterscheide ein fehlendes Dokument von einem unveränderten mithilfe von matchedCount, nicht modifiedCount. Das Update gibt das Dokument nicht zurück; lies es daher erneut mit findOne aus.

challenge icon

Aufgabe

Einfach

Ein Client möchte ein einzelnes Feld eines Buchs korrigieren, zum Beispiel ein falsches Jahr, ohne das ganze Buch erneut zu senden.

  1. Füge in server.js unter dem Kommentar // Add PATCH /books/:id here. eine Route für PATCH /books/:id hinzu.
  2. Beginne wie bei GET /books/:id: Rufe parseId(req, res) auf. Wenn die ID ungültig ist, hat parseId bereits mit 400 geantwortet und gibt null zurück. Beende die Verarbeitung also an dieser Stelle.
  3. Ändere nur die Felder, die der Body sendet, und lasse alle anderen Felder unverändert. Ein Body mit { "year": 1966 } ändert nur das Jahr.
  4. Wenn es kein Buch mit dieser _id gibt, antworte mit dem Status 404 und einem Fehler, zum Beispiel { "error": "No such book" }.
  5. Andernfalls antworte mit dem Status 200 und dem ganzen Buch, so wie es jetzt gespeichert ist:
    { "_id": "6720a1f4c2b9e81d3a5f0c11", "title": "Dune", "author": "Frank Herbert", "year": 1966, "isbn": "9780441013593", "genre": "scifi" }
    Probiere es aus: Sende GET /books und kopiere Dunes _id. Kopiere sie nach jedem „Spielen“ erneut, da bei jedem „Spielen“ neue IDs vergeben werden. Sende PATCH /books/ gefolgt von Dunes _id und dem Body { "year": 1966 }. Du erhältst 200 und Dune mit "year": 1966; alle anderen Felder bleiben unverändert, und im Tab „Data“ wird dasselbe angezeigt. Sende dieselbe Anfrage erneut: Du erhältst weiterhin 200, weil das Buch existiert, auch wenn sich diesmal nichts geändert hat. Sende PATCH /books/000000000000000000000000 mit { "year": 1966 }: Du erhältst 404. Sende PATCH /books/42: Du erhältst 400.

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

// Jeder Fehler liefert { error: message } zurück.
function sendError(res, status, message) {
    res.status(status).json({ error: message });
}

// Die :id als ObjectId oder null, nachdem bei einer ungültigen id mit 400 geantwortet wurde.
function parseId(req, res) {
    if (ObjectId.isValid(req.params.id)) {
        return new ObjectId(req.params.id);
    }
    sendError(res, 400, 'Not a valid id');
    return null;
}

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/newest', async (req, res) => {
    const n = Number(req.query.n) || 3;
    const list = await books
        .find({}, { projection: { title: 1, year: 1, _id: 0 } })
        .sort({ year: -1 })
        .limit(n)
        .toArray();
    res.json(list);
});

app.get('/books/:id', async (req, res) => {
    const id = parseId(req, res);
    if (!id) return;
    const book = await books.findOne({ _id: id });
    if (!book) {
        return sendError(res, 404, 'No such book');
    }
    res.json(book);
});

// Hier PATCH /books/:id hinzufügen.

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