Menu
CoddyTech

Update-Operatoren

Teil des Abschnitts Datenbanken mit MongoDB der Node.js-Journey von Coddy. Lektion 7 von 18.

Das Hinzufügen einer Kopie oder eines Tags sollte ein Buch direkt ändern, ohne es auszulesen, in JavaScript zu ändern und zurückzuschreiben.

$inc addiert eine Zahl zu einem Feld und beginnt bei 0, wenn das Feld fehlt. $push hängt einen Wert an ein Array-Feld an und erstellt das Array, wenn es fehlt. Ein Update kann mehrere Operatoren enthalten:

await players.updateOne(
    { name: 'Ada' },
    { $inc: { wins: 1 }, $push: { badges: 'streak' } }
);

Die Datenbank wendet die Änderung selbst an, sodass zwei Anfragen zum selben Zeitpunkt beide gezählt werden. $set ist hier nicht geeignet: Es ersetzt das gesamte badges-Array durch den Wert, den du angibst.

challenge icon

Aufgabe

Einfach
  • POST /books/:id/copies erhöht copies des Buchs um 1.
  • POST /books/:id/tags mit { "tag": "classic" } fügt das Tag zum Array tags hinzu.
  • Beide antworten mit dem aktualisierten Buch und dem Statuscode 200 oder bei einer unbekannten ID mit 404.

Sende jede Anfrage zweimal und beobachte das Buch im Tab „Data“.

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 wird mit { error: message } beantwortet.
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);
});

app.patch('/books/:id', async (req, res) => {
    const id = parseId(req, res);
    if (!id) return;
    const result = await books.updateOne({ _id: id }, { $set: req.body });
    if (result.matchedCount === 0) {
        return sendError(res, 404, 'No such book');
    }
    res.json(await books.findOne({ _id: id }));
});

app.listen(3000, () => {
    console.log('Bookshelf is running on port 3000');
});

Alle Lektionen in Datenbanken mit MongoDB