Menu
CoddyTech

Aggiornamento dei documenti

Fa parte della sezione Database con MongoDB del percorso Node.js di Coddy. Lezione 14 di 29.

Correggere l'anno di un libro dovrebbe modificare quel campo e lasciare invariati gli altri.

updateOne(filter, update) modifica il primo documento che corrisponde al filtro. L'aggiornamento è composto da operatori: $set scrive i campi che gli indichi e mantiene tutti gli altri. Un oggetto semplice senza operatori viene rifiutato con "Update document requires atomic operators".

const result = await players.updateOne(
    { name: 'Ada' },
    { $set: { score: 120, level: 4 } }
);
result.matchedCount;  // 1 se un giocatore corrispondeva, 0 se nessuno corrispondeva
result.modifiedCount; // 0 se i valori erano già gli stessi

Usa matchedCount, non modifiedCount, per distinguere un documento mancante da uno invariato. L'aggiornamento non restituisce il documento, quindi rileggilo con findOne.

challenge icon

Sfida

Facile

Un cliente vuole correggere un campo di un libro, per esempio un anno errato, senza inviare di nuovo l'intero libro.

  1. In server.js, sotto il commento // Add PATCH /books/:id here., aggiungi una route PATCH /books/:id.
  2. Avviala come inizia ora GET /books/:id: chiama parseId(req, res). Se l'id non è valido, parseId ha già risposto con 400 e restituisce null, quindi fermati lì.
  3. Modifica solo i campi inviati nel body e lascia invariati tutti gli altri. Un body { "year": 1966 } modifica l'anno e nient'altro.
  4. Se non esiste alcun libro con quel _id, rispondi con lo status 404 e un errore, per esempio { "error": "No such book" }.
  5. Altrimenti, rispondi con lo status 200 e l'intero libro così come è salvato ora:
    { "_id": "6720a1f4c2b9e81d3a5f0c11", "title": "Dune", "author": "Frank Herbert", "year": 1966, "isbn": "9780441013593", "genre": "scifi" }
    Prova: invia GET /books e copia l'_id di Dune. Copialo di nuovo dopo ogni esecuzione, perché ogni esecuzione genera nuovi ID. Invia PATCH /books/ seguito dall'_id di Dune, con il body { "year": 1966 }. Ricevi 200 e Dune con "year": 1966, mentre tutti gli altri campi restano invariati; anche la scheda Data mostra lo stesso risultato. Invia di nuovo la stessa richiesta: ricevi ancora 200, perché il libro esiste anche se questa volta non è cambiato nulla. Invia PATCH /books/000000000000000000000000 con { "year": 1966 }: ricevi 404. Invia PATCH /books/42: ricevi 400.

Provalo tu

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

// Ogni errore restituisce { error: message }.
function sendError(res, status, message) {
    res.status(status).json({ error: message });
}

// Il parametro :id come ObjectId, oppure null dopo aver restituito 400 per un id non valido.
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);
});

// Aggiungi PATCH /books/:id qui.

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

Questa lezione include un breve quiz. Inizia la lezione per rispondere e tenere traccia dei tuoi progressi.

Tutte le lezioni di Database con MongoDB

Esercitati da solo: Playground Express