Menu
CoddyTech

Aktualizowanie dokumentów

Część sekcji Bazy danych z MongoDB ścieżki Node.js w Coddy. Lekcja 14 z 29.

Poprawienie roku wydania książki powinno zmienić tylko to jedno pole, pozostawiając pozostałe bez zmian.

updateOne(filter, update) zmienia pierwszy dokument pasujący do filtra. Aktualizacja składa się z operatorów: $set zapisuje podane pola i zachowuje wszystkie pozostałe. Zwykły obiekt bez operatora jest odrzucany z komunikatem "Update document requires atomic operators".

const result = await players.updateOne(
    { name: 'Ada' },
    { $set: { score: 120, level: 4 } }
);
result.matchedCount;  // 1, jeśli znaleziono pasującego gracza, 0, jeśli nie znaleziono żadnego
result.modifiedCount; // 0, jeśli wartości były już takie same

Rozróżnij brak dokumentu od dokumentu, który nie uległ zmianie, za pomocą matchedCount, a nie modifiedCount. Aktualizacja nie zwraca dokumentu, więc odczytaj go ponownie za pomocą findOne.

challenge icon

Wyzwanie

Łatwy

Klient chce poprawić jedno pole książki, na przykład błędny rok, bez ponownego wysyłania całej książki.

  1. W pliku server.js, poniżej komentarza // Add PATCH /books/:id here., dodaj trasę PATCH /books/:id.
  2. Rozpocznij ją tak, jak teraz rozpoczyna się GET /books/:id: wywołaj parseId(req, res). Jeśli identyfikator jest nieprawidłowy, parseId zdążyło już odpowiedzieć kodem 400 i zwraca null, więc zakończ działanie w tym miejscu.
  3. Zmieniaj tylko pola przesłane w treści żądania, a wszystkie pozostałe pozostaw bez zmian. Treść żądania { "year": 1966 } zmienia rok i nic więcej.
  4. Jeśli nie ma książki z takim identyfikatorem _id, odpowiedz kodem statusu 404 i błędem, na przykład { "error": "No such book" }.
  5. W przeciwnym razie odpowiedz kodem statusu 200 i całą książką w postaci, w jakiej jest teraz zapisana:
    { "_id": "6720a1f4c2b9e81d3a5f0c11", "title": "Dune", "author": "Frank Herbert", "year": 1966, "isbn": "9780441013593", "genre": "scifi" }
    Wypróbuj: Wyślij GET /books i skopiuj _id książki Dune. Kopiuj go ponownie po każdym uruchomieniu, ponieważ za każdym razem identyfikatory są nowe. Wyślij PATCH /books/ wraz z _id książki Dune i treścią żądania { "year": 1966 }. Otrzymasz kod 200 i książkę Dune z "year": 1966; wszystkie pozostałe pola pozostaną bez zmian, a karta Data pokaże to samo. Wyślij to samo żądanie ponownie: nadal otrzymasz kod 200, ponieważ książka istnieje, mimo że tym razem nic się nie zmieniło. Wyślij PATCH /books/000000000000000000000000 z { "year": 1966 }: otrzymasz kod 404. Wyślij PATCH /books/42: otrzymasz kod 400.

Spróbuj swoich sił

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

// Każdy błąd zwraca odpowiedź { error: message }.
function sendError(res, status, message) {
    res.status(status).json({ error: message });
}

// Wartość :id jako ObjectId albo null po zwróceniu odpowiedzi 400 dla nieprawidłowego id.
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);
});

// Dodaj tutaj PATCH /books/:id.

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

Ta lekcja zawiera krótki quiz. Zacznij lekcję, żeby na niego odpowiedzieć i śledzić swoje postępy.

Wszystkie lekcje w sekcji Bazy danych z MongoDB

Poćwicz samodzielnie: Edytor online Express