Удаление документов
Часть раздела Базы данных с MongoDB путешествия по Node.js на Coddy. Урок 16 из 29.
Для удаления книги нужен один вызов, но сервер всё равно должен сообщить клиенту, была ли книга для удаления.
deleteOne(filter) удаляет первый подходящий документ и возвращает { deletedCount }: 1, если документ был удалён, и 0, если ничего не совпало. Успешное удаление возвращает 204 No Content — статус без тела ответа, отправляемый с помощью res.status(204).end().
const result = await sessions.deleteOne({ token });
if (result.deletedCount === 0) {
// ни у одной сессии не было такого токена
}Повторное удаление одного и того же идентификатора не должно завершаться успехом. При второй попытке уже нечего удалять, и клиент должен получить ответ 404.
Задание
ЛегкоКлиенты могут удалить книгу, и им нужно знать, была ли книга, которую можно удалить.
- В
server.jsдобавь маршрутDELETE /books/:id. ИспользуйparseIdдля некорректного идентификатора: в этом случае возвращается статус 400. - Когда маршрут удаляет книгу, ответь статусом 204 без тела ответа. Заверши ответ, не отправляя JSON.
- Если книги с таким значением
_idнет, ответь статусом 404 и сообщением об ошибке, например{ "error": "No such book" }. Поэтому при повторном удалении той же книги тоже возвращается статус 404: её уже нет. Попробуй: отправьGET /booksи скопируй_idкниги Emma. ОтправьDELETE /books/<Emma's _id>: получишь статус 204 и пустое тело ответа. Отправь тот же запрос ещё раз: получишь статус 404. ОтправьGET /books/<Emma's _id>: тоже получишь статус 404. ОтправьGET /books: останутся только Dune и Kindred, а на вкладке Data отобразятся две книги. Нажми «Запустить», чтобы вернуть Emma.
Попробуйте сами
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());
// При любой ошибке возвращается ответ { error: message }.
function sendError(res, status, message) {
res.status(status).json({ error: message });
}
// Преобразует :id в ObjectId или возвращает null после ответа с кодом 400, если id некорректен.
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');
});
Все уроки раздела Базы данных с MongoDB
2Изменение документов
Обновление документовОператоры обновленияПотренируйтесь самостоятельно: Песочница Express