Mongoose Ara Katmanı: Önce ve Sonra Kancaları
Öğrenenler, kaydetmeden önce parolaları özetleme veya find sonrasında günlük kaydı tutma gibi görevler için belge ve sorgu ara katmanı kancaları yazacaklardır.
Mongoose Ara Katmanı: Önce ve Sonra Kancaları, CoddyKit'te ücretsiz bir MongoDB Academy dersidir. Bu, 4 dersinin 4. dersidir. Aşağıdan dersin tamamını ücretsiz okuyabilir, sonra tarayıcıda yerleşik kod editörü ve 7/24 yapay zeka koçu ile uygulamalı olarak pratik yapabilirsin. Bu, MongoDB Academy öğrenme yolunun bir parçasıdır ve ilerlemeniz web ve CoddyKit uygulaması arasında senkronize olur. MongoDB Academy kursu toplamda 4 dersten oluşur.
Mongoose Ara Yazılımı Nedir?
Mongoose ara yazılımı (kanca olarak da adlandırılır), save, find, updateOne, deleteOne ve diğerleri gibi belirli işlemlerden önce veya sonra çalışan işlevlerdir. Rota işleyicilerinizi karmaşıklaştırmadan belge ve sorgu işlemlerinin yaşam döngüsüne özel mantık eklemenizi sağlarlar. Yaygın kullanım alanları arasında kaydetmeden önce parolaları özetlemek, sorgu sürelerini günlüğe kaydetmek, geçici silmeleri zorunlu kılmak ve find sonrasında ilişkili verileri doldurmak bulunur.
İki Tür: Belge ve Sorgu Ara Yazılımı
Mongoose'da iki farklı ara yazılım kategorisi vardır: Belge ara yazılımı, belirli bir Document örneği üzerindeki işlemlere bağlanır (save, validate, remove, init). Sorgu ara yazılımı ise Model üzerinde çağrılan sorgu işlemlerine bağlanır (find, findOne, updateOne, deleteOne vb.). Temel fark, this ifadesinin neyi belirttiğidir: belge ara yazılımında this belgeyi, sorgu ara yazılımında ise sorgu nesnesini belirtir.
// Document middleware: 'this' = the document
userSchema.pre('save', function () {
console.log('Saving document:', this.email);
});
// Query middleware: 'this' = the Query object
userSchema.pre('find', function () {
console.log('Running query:', this.getQuery());
});Kaydetme Öncesi: Parolaları Özetleme
Kaydetme öncesi kancası, en yaygın belge ara yazılımıdır. Bir belge MongoDB'ye kaydedilmeden önce çalışır. Tipik kullanım alanı parolaları özetlemektir: bir kullanıcı belgesi yeni veya değiştirilmiş bir parolayla kaydedildiğinde, parolayı saklamadan önce bcrypt ile özetleyin. this.isModified('password') denetimi, ilgisiz kaydetme işlemlerinde daha önce özetlenmiş bir parolanın yeniden özetlenmesini önler.
const bcrypt = require('bcrypt');
userSchema.pre('save', async function () {
// 'this' is the User document being saved
if (!this.isModified('password')) {
return; // skip if password hasn't changed
}
const saltRounds = 12;
this.password = await bcrypt.hash(this.password, saltRounds);
// The hashed value replaces the plain password before MongoDB stores it
});isNew ve isModified Yardımcıları
Belge ara yazılımı izleme yardımcılarına erişebilir: belge ilk kez eklenirken (güncellenirken değil) this.isNew değeri true olur. this.isModified(path), belirtilen alanın belge son kez kaydedildiğinden veya alındığından bu yana değiştirilip değiştirilmediğini belirtir. Bu yardımcılar, kancaları koşullu olarak çalıştırmanızı sağlar; örneğin yalnızca oluşturma sırasında veya yalnızca belirli bir alan değiştiğinde.
userSchema.pre('save', async function () {
if (this.isNew) {
// Only runs when creating a new user, not on updates
this.verificationToken = crypto.randomBytes(32).toString('hex');
this.verificationExpires = new Date(Date.now() + 24 * 60 * 60 * 1000);
}
if (this.isModified('email')) {
// Only runs when the email field specifically changed
this.emailVerified = false; // reset verification on email change
}
});Kaydetme Sonrası: Kayıttan Sonraki Yan Etkiler
Kaydetme sonrası kancalar, bir belge başarıyla kalıcı olarak kaydedildikten sonra çalışır. İlk bağımsız değişken olarak kaydedilmiş belgeyi ve (eski Mongoose sürümlerinde) bir next geri çağırma işlevini alırlar. Kaydetme başarılı olduktan sonra gerçekleşmesi gereken yan etkiler için kanca sonrası işlemler idealdir: hoş geldiniz e-postası göndermek, arama dizinini güncellemek, bir ileti kuyruğuna olay yayımlamak veya önbelleği temizlemek. Kanca sonrası işlemlerde oluşan hatalar kaydetme işlemini geri almaz.
userSchema.post('save', async function (doc) {
// 'doc' is the saved document
if (doc.isNew) {
// Note: 'isNew' is false here (doc was just saved, so it's no longer new)
// Track this with a flag set in pre-save:
}
});
// Pattern: set a flag in pre-save, read it in post-save
userSchema.pre('save', function () {
this._wasNew = this.isNew; // save state before it changes
});
userSchema.post('save', async function (doc) {
if (doc._wasNew) {
await sendWelcomeEmail(doc.email, doc.name);
await analyticsTracker.track('user_created', { userId: doc._id });
}
});Sorgu Ara Yazılımı: Silinenleri Gizlemek İçin Pre-find
Klasik bir sorgu ara yazılımı deseni, mantıksal silme uygulamaktır. Belgeleri kaldırmak yerine bir deletedAt alanı ayarlayın. Ardından her find sorgusuna otomatik olarak { deletedAt: null } ekleyen bir pre('find') kancası ekleyin; böylece silinen belgelerin varsayılan olarak döndürülmemesi sağlanır. Bu yaklaşım, mantıksal silme işlemini uygulamanın geri kalanı için görünmez kılarken bir denetim izi sağlar.
const postSchema = new mongoose.Schema({
title: String,
content: String,
deletedAt: { type: Date, default: null }
});
// Automatically exclude soft-deleted documents from all find queries
postSchema.pre(/^find/, function () {
// 'this' is the Query object
this.where({ deletedAt: null });
// /^find/ matches find, findOne, findOneAndUpdate, etc.
});
// Now Post.find({}) never returns deleted posts
// To explicitly query deleted posts, you'd call Post.find({}).bypassMiddleware() or use .lean() with the native driverSorgu Ara Yazılımı: Pre-find ile Otomatik İlişkilendirme
Her find işleminde bir başvuru alanını otomatik olarak ilişkilendirmek için sorgu ara yazılımını kullanabilirsiniz. Bu sayede çağıranların her sorguya .populate() eklemesine gerek kalmadan başvurulan belgenin her zaman çözümlenmesi sağlanır. Kullanışlı olsa da dikkatli olun: otomatik ilişkilendirme her find işlemi için ikinci bir sorgu ekler ve başvuru büyükse veya her zaman gerekmiyorsa performansı düşürebilir.
const reviewSchema = new mongoose.Schema({
productId: { type: mongoose.Schema.Types.ObjectId, ref: 'Product' },
userId: { type: mongoose.Schema.Types.ObjectId, ref: 'User' },
rating: Number,
comment: String
});
// Always populate author info on find
reviewSchema.pre(/^find/, function () {
this.populate({
path: 'userId',
select: 'name avatar'
});
});
// Now Review.find() always includes user name and avatarPre-deleteOne: Kademeli Silme
Mongoose, bir üst belge silindiğinde ilişkili belgelerin silinmesini (kademeli silme) otomatik olarak uygulamaz. Belge ara yazılımını kullanarak kademeli davranışı uygulayabilirsiniz. Bir User modelindeki pre-deleteOne kancası, kullanıcı belgesinin kendisi kaldırılmadan önce o kullanıcıya ait tüm gönderileri, yorumları ve oturumları silebilir. Bu, yabancı anahtar kısıtlamaları olmadan başvuru bütünlüğünü korur.
userSchema.pre('deleteOne', { document: true, query: false }, async function () {
// 'this' is the User document being deleted
const userId = this._id;
// Cascade delete related documents
await Promise.all([
Post.deleteMany({ authorId: userId }),
Comment.deleteMany({ userId: userId }),
Session.deleteMany({ userId: userId }),
Notification.deleteMany({ userId: userId })
]);
console.log('Cascade deleted data for user:', userId);
});
// Trigger:
// const user = await User.findById(id);
// await user.deleteOne(); // triggers pre-deleteOne aboveAra Yazılımda Hata Yönetimi
Bir pre-kanca işlevi hata fırlatırsa veya bir Promise'ı reddederse, kendisinden önce geldiği işlem iptal edilir. Bu, ara yazılımda doğrulama veya yetkilendirme denetimleri gerçekleştirmenize ve hata fırlatarak kaydetme ya da sorgu işlemlerini iptal etmenize olanak tanır. Örneğin, iş kurallarını (yalnızca şema doğrulamasını değil) doğrulayan bir pre-save kancası, uygulama kodundaki .save() çağrısının catch bloğuna kadar iletilen bir hata fırlatabilir.
orderSchema.pre('save', async function () {
if (this.total <= 0) {
throw new Error('Order total must be positive');
}
// Check inventory synchronously before saving the order
const product = await Product.findById(this.productId).lean();
if (!product || product.stock < this.quantity) {
throw new Error('Insufficient inventory for this order');
}
});
// In route handler:
try {
const order = new Order({ productId, quantity, total });
await order.save(); // throws if pre-save hook rejects
} catch (err) {
res.status(400).json({ error: err.message });
}Toplama Ara Yazılımı
Mongoose, toplama işlem hatları için de ara yazılımı destekler. Bir pre-aggregate kancası, MongoDB'ye gönderilmeden önce işlem hattı dizisine erişmenizi sağlar; böylece aşamaların başına (silinen belgeleri filtrelemek gibi) veya sonuna (varsayılan bir limit eklemek gibi) aşamalar ekleyebilirsiniz. İşlem hattına kanca işlevinin içinde this.pipeline() üzerinden erişin.
postSchema.pre('aggregate', function () {
// 'this' is the Aggregate object
// Add a $match stage at the beginning to exclude soft-deleted documents
this.pipeline().unshift({
$match: { deletedAt: null }
});
});
// Now Post.aggregate([...]) automatically excludes deleted posts
// at the start of every aggregation pipelineAra Yazılımın Tuzakları: Kancaları Atlama İhtimali Olan Sorgu Yöntemleri
Tüm yazma işlemleri belge ara yazılımını tetiklemez. updateMany(), findOneAndUpdate() ve replaceOne(), bir örnek üzerinde değil de Model üzerinde çağrıldığında belge save kancalarını atlar; bunlar sorgu ara yazılımıdır ve onları yakalamak istiyorsanız ayrı kancalara ihtiyaç duyar. Örneğin, pre-save parola özütleme kancası User.updateOne({}, { $set: { password: plain } }) çağrıldığında çalışmaz. Sorgu tabanlı güncellemelerde parolayı her zaman uygulama kodunda özütleyin.
// WRONG: password NOT hashed — bypasses pre-save hook
await User.updateOne({ _id: userId }, { $set: { password: plainPassword } });
// RIGHT for query-level updates: hash before calling updateOne
const hashed = await bcrypt.hash(plainPassword, 12);
await User.updateOne({ _id: userId }, { $set: { password: hashed } });
// Or: fetch, modify, save — triggers pre-save hook
const user = await User.findById(userId);
user.password = plainPassword; // hook will hash it
await user.save();Kısa Kontrol
Bu derste MongoDB ve NoSQL Veritabanları kavramlarını ne kadar anladığınızı test edin.
Ders Özeti
Bu derste şunları öğrendiniz: pre kancaları bir işlemden önce çalışır ve hata fırlatarak işlemi iptal edebilir; post kancaları ise işlemden sonra çalışır ve sonucu bağımsız değişken olarak alır, belge ara yazılımı (pre-save, pre-deleteOne) için 'this' belgenin kendisidir; sorgu ara yazılımı içinse 'this', Query nesnesidir ve sorgu düzeyindeki yazma yöntemleri (updateOne, updateMany, findOneAndUpdate) belge ara yazılımını atlar — her işlem türünde hangi kancaların çalıştığına her zaman dikkat edin. Böylece MongoDB ve NoSQL Veritabanları kurs yolunu tamamladınız!
Yapay zeka eğitmeniyle JavaScript öğren — ücretsiz
Tarayıcında gerçek kod yaz ve çalıştır, 7/24 yapay zeka eğitmeninden anında yardım al; web'de ya da uygulamada kaldığın yerden devam et.
- Kurslar
- 30
- Dersler
- 120
Sıkça Sorulan Sorular
“Mongoose Ara Katmanı: Önce ve Sonra Kancaları” dersi ücretsiz mi?
Evet — “Mongoose Ara Katmanı: Önce ve Sonra Kancaları” dersin tüm metni burada web'de ücretsiz olarak okunabilir. Etkileşimli olarak pratik yapmak (yerleşik kod editörü ve 7/24 yapay zeka koçu) ve MongoDB Academy kursunun geri kalanını açmak için CoddyKit PRO'ya yükselt. MongoDB Academy kursu toplamda 4 dersten oluşur.
“Mongoose Ara Katmanı: Önce ve Sonra Kancaları” dersinde ne öğreneceğim?
Öğrenenler, kaydetmeden önce parolaları özetleme veya find sonrasında günlük kaydı tutma gibi görevler için belge ve sorgu ara katmanı kancaları yazacaklardır. MongoDB Academy ile uygulamalı kodu tarayıcıda doğrudan çalıştırarak pratik yaparsın ve 7/24 yapay zeka koçu dersi çalışırken sorularını yanıtlar.
MongoDB Academy öğrenmeye başlamak için deneyim gerekli mi?
Önceden deneyim gerekmez. CoddyKit'te MongoDB Academy, başlangıçtan ileri seviyeye kadar yapılandırıldığı için buradan başlayabilir veya başından başlayıp kendi hızında ilerleme yapabilirsin. Bu, 4 dersinin 4. dersidir.
“Mongoose Ara Katmanı: Önce ve Sonra Kancaları” dersi ne kadar sürer?
Çoğu CoddyKit dersi yaklaşık 5–10 dakika sürer. Her biri kısa ve etkileşimli olduğu için sabit ilerleme yaparsın ve web ile uygulama arasında tam olarak bıraktığın yerden devam edebilirsin.
Bu MongoDB Academy dersinde kod yazıp çalıştırabilir miyim?
Evet. Her MongoDB Academy dersi yerleşik bir kod editörü içerir, bu sayede tarayıcıda gerçek kod yazıp çalıştırabilir ve anlık yapay zeka geri bildirimi alırsın — yerel kurulum gerekli değildir.
Bu kursun tüm dersleri
- Resmî Node.js Sürücüsüyle Bağlanma
- Mongoose Şemaları, Modelleri ve Sanal Özellikleri
- Mongoose Sorguları, Zincirleme ve Lean Belgeler
- Mongoose Ara Katmanı: Önce ve Sonra Kancaları