Menu
CoddyTech

Mettre à jour les documents

Fait partie de la section Bases de données avec MongoDB du Journey Node.js de Coddy. Leçon 14 sur 29.

Corriger l’année d’un livre devrait modifier ce seul champ et laisser les autres intacts.

updateOne(filter, update) modifie le premier document correspondant au filtre. La mise à jour est composée d’opérateurs : $set écrit les champs que tu lui indiques et conserve tous les autres. Un objet ordinaire sans opérateur est refusé avec le message "Update document requires atomic operators".

const result = await players.updateOne(
    { name: 'Ada' },
    { $set: { score: 120, level: 4 } }
);
result.matchedCount;  // 1 si un joueur correspond, 0 sinon
result.modifiedCount; // 0 si les valeurs étaient déjà les mêmes

Distingue un document manquant d’un document inchangé avec matchedCount, et non avec modifiedCount. La mise à jour ne renvoie pas le document : relis-le avec findOne.

challenge icon

Défi

Facile

Un client veut corriger un champ d’un livre, comme une année erronée, sans renvoyer le livre entier.

  1. Dans server.js, sous le commentaire // Add PATCH /books/:id here., ajoute une route PATCH /books/:id.
  2. Commence comme la route GET /books/:id actuelle : appelle parseId(req, res). Si l’identifiant est incorrect, parseId a déjà répondu avec le statut 400 et renvoie null, alors arrête-toi là.
  3. Modifie uniquement les champs envoyés dans le corps de la requête et laisse tous les autres champs tels quels. Un corps de requête { "year": 1966 } modifie l’année et rien d’autre.
  4. Si aucun livre ne possède cet _id, réponds avec le statut 404 et une erreur, par exemple { "error": "No such book" }.
  5. Sinon, réponds avec le statut 200 et le livre entier tel qu’il est maintenant enregistré :
    { "_id": "6720a1f4c2b9e81d3a5f0c11", "title": "Dune", "author": "Frank Herbert", "year": 1966, "isbn": "9780441013593", "genre": "scifi" }
    Essaie : Envoie GET /books et copie l’_id de Dune. Recopie-le après chaque clic sur « Jouer », car chaque exécution génère de nouveaux identifiants. Envoie PATCH /books/ suivi de l’_id de Dune, avec le corps de requête { "year": 1966 }. Tu obtiens le statut 200 et Dune avec "year": 1966, tous les autres champs étant inchangés, et l’onglet Data affiche la même chose. Envoie à nouveau la même requête : tu obtiens toujours le statut 200, car le livre existe, même si rien n’a changé cette fois-ci. Envoie PATCH /books/000000000000000000000000 avec { "year": 1966 } : tu obtiens le statut 404. Envoie PATCH /books/42 : tu obtiens le statut 400.

Essayez vous-même

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

// Chaque erreur renvoie { error: message }.
function sendError(res, status, message) {
    res.status(status).json({ error: message });
}

// Le :id sous forme d’ObjectId, ou null après avoir renvoyé 400 si l’id est invalide.
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);
});

// Ajoutez PATCH /books/:id ici.

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

Cette leçon comprend un petit quiz. Commencez la leçon pour y répondre et suivre votre progression.

Toutes les leçons de Bases de données avec MongoDB

Entraînez-vous par vous-même : Playground Express