Обновление документов
Часть раздела Базы данных с MongoDB путешествия по Node.js на Coddy. Урок 14 из 29.
Исправление года издания книги должно изменить только это поле, оставив остальные без изменений.
updateOne(filter, update) изменяет первый документ, соответствующий фильтру. Обновление состоит из операторов: $set записывает указанные вами поля и сохраняет все остальные. Простой объект без оператора отклоняется с сообщением "Update document requires atomic operators".
const result = await players.updateOne(
{ name: 'Ada' },
{ $set: { score: 120, level: 4 } }
);
result.matchedCount; // 1, если игрок найден, 0 — если нет
result.modifiedCount; // 0, если значения уже были такими жеОтличайте отсутствующий документ от документа без изменений с помощью matchedCount, а не modifiedCount. Результат обновления не содержит документ, поэтому прочитайте его снова с помощью findOne.
Задание
ЛегкоКлиент хочет исправить одно поле книги, например неверный год, не отправляя книгу целиком повторно.
- В
server.js, ниже комментария// Add PATCH /books/:id here., добавь маршрутPATCH /books/:id. - Начни его так же, как сейчас начинается
GET /books/:id: вызовиparseId(req, res). Если идентификатор некорректен,parseIdуже отправила ответ с кодом 400 и вернулаnull, поэтому остановись на этом. - Измени только те поля, которые переданы в теле запроса, а все остальные оставь без изменений. Тело
{ "year": 1966 }изменит только год. - Если книги с таким
_idнет, отправь ответ со статусом 404 и ошибкой, например{ "error": "No such book" }. - В противном случае отправь ответ со статусом 200 и всю книгу в том виде, в каком она хранится сейчас:Попробуй: отправь
{ "_id": "6720a1f4c2b9e81d3a5f0c11", "title": "Dune", "author": "Frank Herbert", "year": 1966, "isbn": "9780441013593", "genre": "scifi" }GET /booksи скопируй_idкниги Dune. Копируй его заново после каждого запуска, потому что при каждом запуске создаются новые идентификаторы. ОтправьPATCH /books/и добавь_idкниги Dune, указав тело{ "year": 1966 }. В ответ ты получишь код 200 и книгу Dune с"year": 1966; все остальные поля останутся без изменений, и на вкладке Data будет показано то же самое. Отправь тот же запрос ещё раз: ты по-прежнему получишь код 200, потому что книга существует, хотя на этот раз ничего не изменилось. ОтправьPATCH /books/000000000000000000000000с телом{ "year": 1966 }: ты получишь код 404. ОтправьPATCH /books/42: ты получишь код 400.
Попробуйте сами
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);
});
// Добавьте PATCH /books/:id здесь.
app.listen(3000, () => {
console.log('Bookshelf is running on port 3000');
});
В этом уроке есть небольшой тест. Начните урок, чтобы ответить на вопросы и сохранить прогресс.
Все уроки раздела Базы данных с MongoDB
2Изменение документов
Обновление документовОператоры обновленияПотренируйтесь самостоятельно: Песочница Express