Menu
CoddyTech

Supprimer des documents

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

Supprimer un livre ne nécessite qu’un seul appel, mais le serveur doit quand même indiquer au client s’il y avait un livre à supprimer.

deleteOne(filter) supprime le premier document correspondant et renvoie { deletedCount } : 1 lorsqu’un document a été supprimé, 0 lorsqu’aucun ne correspond. Une suppression réussie renvoie 204 No Content, un statut sans corps, envoyé avec res.status(204).end().

const result = await sessions.deleteOne({ token });
if (result.deletedCount === 0) {
    // aucune session ne possédait ce token
}

La suppression du même identifiant deux fois ne devrait pas réussir deux fois. La deuxième fois, il ne reste rien, et le client devrait recevoir une réponse 404.

challenge icon

Défi

Facile

Les clients peuvent supprimer un livre, et ils doivent savoir s’il y avait un livre à supprimer.

  1. Dans server.js, ajoute une route DELETE /books/:id. Utilise parseId pour un identifiant incorrect ; cela renvoie le statut 400.
  2. Lorsque la route supprime un livre, réponds avec le statut 204 et sans aucun corps. Termine la réponse sans envoyer de JSON.
  3. Lorsqu’aucun livre ne possède cet _id, réponds avec le statut 404 et une erreur, par exemple { "error": "No such book" }. Ainsi, supprimer le même livre une deuxième fois renvoie également le statut 404, puisqu’il a déjà été supprimé. Essaie : Envoie GET /books et copie le _id d’Emma. Envoie DELETE /books/<Emma's _id> : tu obtiens le statut 204 et un corps vide. Envoie la même requête une deuxième fois : tu obtiens le statut 404. Envoie GET /books/<Emma's _id> : tu obtiens aussi le statut 404. Envoie GET /books : tu obtiens uniquement Dune et Kindred, et l’onglet Data affiche deux livres. Appuie sur « Jouer » pour récupérer Emma.

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 paramètre :id sous forme d’ObjectId, ou null après avoir renvoyé 400 si l’identifiant 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);
});

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.post('/books/:id/copies', async (req, res) => {
    const id = parseId(req, res);
    if (!id) return;
    const result = await books.updateOne({ _id: id }, { $inc: { copies: 1 } });
    if (result.matchedCount === 0) {
        return sendError(res, 404, 'No such book');
    }
    res.json(await books.findOne({ _id: id }));
});

app.post('/books/:id/tags', async (req, res) => {
    const id = parseId(req, res);
    if (!id) return;
    const result = await books.updateOne({ _id: id }, { $push: { tags: req.body.tag } });
    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');
});

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

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