Benzersiz İndeksler
Coddy'nin Node.js Journey'sinin MongoDB ile Veritabanları bölümünün bir parçası. Ders 17 / 29.
Aynı ISBN'ye sahip iki kitap asla birlikte saklanmamalıdır ve her eklemeden önce findOne kullanmak bir boşluk bırakır: iki istek de hiçbir şey bulamayabilir ve ikisi de ekleme yapabilir.
İndeks, veritabanının belgeleri hızlıca bulmak için bir koleksiyonun yanında tuttuğu, bir alanın değerlerinden oluşan sıralı bir listedir. Benzersiz indeks, tuttuğu bir değere sahip ikinci bir belgeyi de reddeder: ekleme, MongoServerError hatasıyla birlikte 11000 kodunu ve "E11000 duplicate key error" mesajını verir.
await users.createIndex({ email: 1 }, { unique: true });
try {
await users.insertOne({ email: 'ada@example.com' });
} catch (err) {
if (err.code !== 11000) throw err;
// e-posta adresi zaten kullanılıyor
}Verileri eklemeden önce, başlangıçta indeksi oluştur. Var olan bir indeksi oluşturmak hiçbir şey yapmaz.
Görev
Kolayİki istek aynı anda gelse bile aynı ISBN'yi paylaşan iki kitap olamaz. Veritabanının yinelenen kaydı reddetmesini sağla.
server.jsdosyasının en üstünde,isbnalanı üzerinde benzersiz bir indeks oluştur. Bunu, başlangıç kodu üç kitabıinsertManyile kaydetmeden önce yap ve işlem içinawaitkullan.POST /booksiçinde, ISBN zaten kayıtlıysa ekleme artık hata verir. Bu hatayı yakala.codedeğeri11000ise 409 durum koduyla ve örneğin{ "error": "That ISBN is already on the shelf" }gibi bir hatayla yanıt ver. Diğer hataları yeniden fırlat; böylece Express 500 yanıtı verir.- Yeni ISBN'li bir kitap, önceki gibi yine 201 durum kodu ve kaydedilen kitapla yanıt alır. Şunu dene: Dune'un ikinci bir kopyası için
POST /booksisteği gönder:{ "title": "Dune", "author": "Frank Herbert", "year": 1965, "isbn": "9780441013593", "genre": "scifi" }. 409 durum kodu ve hata alırsın.GET /booksisteği gönder: yine üç kitap alırsın ve Data sekmesinde Dune bir kez görünür.POST /booksisteğini{ "title": "Beloved", "author": "Toni Morrison", "year": 1987, "isbn": "9781400033416", "genre": "literary" }ile gönder: 201 durum kodu alırsın.
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');
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 });
}
// Geçerli bir :id için ObjectId, geçersiz bir id için 400 yanıtı verildikten sonra null döndürülü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;
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.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.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
2Belgeleri Değiştirme
Belgeleri GüncellemeGüncelleme OperatörleriKendi başına pratik yap: Express playground