Eliminación de documentos
Parte de la sección Bases de datos con MongoDB del Journey de Node.js de Coddy. Lección 16 de 29.
Eliminar un libro requiere una sola llamada, pero el servidor aún tiene que informar al cliente de si había un libro que eliminar.
deleteOne(filter) elimina el primer documento coincidente y devuelve { deletedCount }: 1 si eliminó uno, 0 si no hubo coincidencias. Una eliminación correcta devuelve 204 No Content, un estado que no tiene cuerpo, enviado con res.status(204).end().
const result = await sessions.deleteOne({ token });
if (result.deletedCount === 0) {
// ninguna sesión tenía ese token
}Eliminar el mismo id dos veces no debería tener éxito ambas veces. La segunda vez ya no queda nada y el cliente debería recibir un 404.
Desafío
FácilLos clientes pueden eliminar un libro y necesitan saber si había un libro que eliminar.
- En
server.js, añade una rutaDELETE /books/:id. UsaparseIdpara un id no válido; la respuesta será 400. - Cuando la ruta elimine un libro, responde con el estado 204 y sin cuerpo. Finaliza la respuesta sin enviar JSON.
- Cuando ningún libro tenga ese
_id, responde con el estado 404 y un error, por ejemplo{ "error": "No such book" }. Por eso, al eliminar el mismo libro por segunda vez también se obtiene 404, porque ya no está. Pruébalo: EnvíaGET /booksy copia el_idde Emma. EnvíaDELETE /books/<Emma's _id>: obtendrás 204 y un cuerpo vacío. Envía la misma solicitud otra vez: obtendrás 404. EnvíaGET /books/<Emma's _id>: también obtendrás 404. EnvíaGET /books: solo obtendrás Dune y Kindred, y la pestaña Data mostrará dos libros. Pulsa «Ejecutar» para recuperar a Emma.
Pruébalo tú mismo
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());
// Cada error devuelve { error: message }.
function sendError(res, status, message) {
res.status(status).json({ error: message });
}
// El :id como ObjectId, o null después de responder con 400 si el id no es válido.
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');
});
Todas las lecciones de Bases de datos con MongoDB
1Documentos
Un libro como documentoColecciones y bases de datosConexión a MongoDBLectura de documentos almacenadosInserción de documentosBúsqueda de un documentoBúsqueda por ObjectIdComparación de númerosFiltros de consultaSelección de los campos devueltosOrdenación de los resultados de consultaConservar los primeros resultadosProyección, ordenación y límite2Modificación de documentos
Actualización de documentosOperadores de actualizaciónPractica por tu cuenta: Playground de Express