Belgeleri Sayma
Coddy'nin Node.js Journey'sinin MongoDB ile Veritabanları bölümünün bir parçası. Ders 19 / 29.
Bir gösterge paneli sayılara ihtiyaç duyar ve yalnızca dizinin uzunluğunu okumak için her belgeyi yüklemek, veritabanının hepsini göndermesine neden olur.
countDocuments(filter), eşleşen belgelerden hiçbirini göndermeden kaç tane olduklarını söyler. Filtre verilmezse koleksiyonun tamamını sayar.
const open = await tickets.countDocuments({ status: 'open' });
const all = await tickets.countDocuments();Filtreyi, GET /books uç noktasının yaptığı gibi sorgudan oluştur ve aynı filtreyi sayım işlemine ilet. Filtreyi dikkate almayan bir sayım yanlış soru için doğru sayıyı verir: istemci açık biletleri sormuşken tüm biletleri sayar.
Görev
KolayBir kontrol paneli, kaç kitap ve puanlama olduğunu gösterir. Her belgeyi yüklemek yerine bunları veritabanında sayın.
server.jsiçinde,// Add GET /stats here.yorumunun altına birGET /statsrotası ekleyin.- Bu rota 200 durum koduyla ve her koleksiyondaki belge sayısıyla yanıt verir. Başlangıçtaki kitaplar ve hiç puanlama olmadığında sonuç şöyledir:
{ "books": 3, "ratings": 0 } ?genre=scifi,bookssayımının yalnızca bu türdeki kitapları saymasını sağlar. Tür ne olursa olsunratingsher zaman tüm puanlamaları sayar. Deneyin:GET /statsisteğini gönderin:{ "books": 3, "ratings": 0 }sonucunu alırsınız.GET /stats?genre=scifiisteğini gönderin:{ "books": 2, "ratings": 0 }.GET /stats?genre=poetryisteğini gönderin:{ "books": 0, "ratings": 0 }.GET /booksyanıtından Dune kitabının_iddeğerini kopyalayın, ardındanPUT /books/<Dune's _id>/ratingsisteğini{ "user": "ada", "stars": 4 }ile gönderin.GET /statsisteğini tekrar gönderin:{ "books": 3, "ratings": 1 }.
Kendin dene
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');
const ratings = db.collection('ratings');
await books.createIndex({ isbn: 1 }, { unique: true });
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());
// Her hata { error: message } biçiminde yanıt verir.
function sendError(res, status, message) {
res.status(status).json({ error: message });
}
// :id değerini ObjectId olarak döndürür; geçersiz bir id için 400 yanıtı verdikten sonra null döndürür.
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;
try {
await books.insertOne(book);
} catch (err) {
if (err.code === 11000) {
return sendError(res, 409, 'That ISBN is already on the shelf');
}
throw err;
}
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.delete('/books/:id', async (req, res) => {
const id = parseId(req, res);
if (!id) return;
const result = await books.deleteOne({ _id: id });
if (result.deletedCount === 0) {
return sendError(res, 404, 'No such book');
}
res.status(204).end();
});
app.put('/books/:id/ratings', async (req, res) => {
const id = parseId(req, res);
if (!id) return;
const { user, stars } = req.body;
await ratings.updateOne({ bookId: id, user }, { $set: { stars } }, { upsert: true });
res.json({ user, stars });
});
app.get('/books/:id/ratings', async (req, res) => {
const id = parseId(req, res);
if (!id) return;
res.json(await ratings.find({ bookId: id }).toArray());
});
// GET /stats uç noktasını buraya ekleyin.
app.listen(3000, () => {
console.log('Bookshelf is running on port 3000');
});
Bu ders kısa bir quiz içerir. Soruları yanıtlamak ve ilerlemeni kaydetmek için derse başla.
MongoDB ile Veritabanları bölümündeki tüm dersler
Kendi başına pratik yap: Express playground