Actualización de documentos
Parte de la sección Bases de datos con MongoDB del Journey de Node.js de Coddy. Lección 14 de 29.
Corregir el año de un libro debería cambiar ese campo y dejar los demás intactos.
updateOne(filter, update) cambia el primer documento que coincide con el filtro. La actualización se compone de operadores: $set escribe los campos que le indicas y conserva todos los demás. Se rechaza un objeto simple sin operadores con el mensaje "Update document requires atomic operators".
const result = await players.updateOne(
{ name: 'Ada' },
{ $set: { score: 120, level: 4 } }
);
result.matchedCount; // 1 si se encontró un jugador que coincidía, 0 si no se encontró ninguno
result.modifiedCount; // 0 cuando los valores ya eran los mismosUsa matchedCount, no modifiedCount, para distinguir un documento inexistente de uno que no se modificó. La actualización no devuelve el documento, así que vuelve a leerlo con findOne.
Desafío
FácilUn cliente quiere corregir un campo de un libro, como un año incorrecto, sin volver a enviar el libro completo.
- En
server.js, debajo del comentario// Add PATCH /books/:id here., añade una rutaPATCH /books/:id. - Empieza de la misma manera que empieza ahora
GET /books/:id: llama aparseId(req, res). Si el id no es válido,parseIdya ha respondido con 400 y devuelvenull, así que detente ahí. - Cambia solo los campos que envía el cuerpo y deja todos los demás como estaban. Un cuerpo
{ "year": 1966 }cambia el año y nada más. - Si no hay ningún libro con ese
_id, responde con el estado 404 y un error, por ejemplo{ "error": "No such book" }. - De lo contrario, responde con el estado 200 y el libro completo tal como está almacenado ahora:Pruébalo: Envía
{ "_id": "6720a1f4c2b9e81d3a5f0c11", "title": "Dune", "author": "Frank Herbert", "year": 1966, "isbn": "9780441013593", "genre": "scifi" }GET /booksy copia el_idde Dune. Vuelve a copiarlo después de cada ejecución, porque cada ejecución genera nuevos id. EnvíaPATCH /books/seguido del_idde Dune, con el cuerpo{ "year": 1966 }. Obtienes 200 y Dune con"year": 1966, con todos los demás campos sin cambios, y la pestaña Data muestra lo mismo. Envía la misma solicitud otra vez: sigues obteniendo 200, porque el libro existe aunque esta vez no haya cambiado nada. EnvíaPATCH /books/000000000000000000000000con{ "year": 1966 }: obtienes 404. EnvíaPATCH /books/42: obtienes 400.
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 responde con { 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);
});
// Añade PATCH /books/:id aquí.
app.listen(3000, () => {
console.log('Bookshelf is running on port 3000');
});
Esta lección incluye un breve cuestionario. Empieza la lección para responderlo y registrar tu progreso.
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