Node.js İle Mongoose Kullanarak Veri Doğrulama İşlemi Nasıl Yapılır?

Ön Hazırlık ve Gereksinimler

Uygulamaya başlamadan önce sisteminizde Node.js (v20 veya üzeri) ve MongoDB'nin kurulu olması gerekmektedir. Projenizi başlatmak ve gerekli kütüphaneleri kurmak için aşağıdaki adımları takip edin.

  1. Proje klasörünüzü oluşturun ve terminalde içine girin.
  2. npm init -y komutu ile package.json dosyasını oluşturun.
  3. Mongoose paketini yüklemek için npm install mongoose komutunu çalıştırın.

Bu hazırlıklar, Mongoose'un sunduğu yerleşik doğrulayıcıları (built-in validators) kullanabilmeniz için temel ortamı sağlar. Mongoose, MongoDB'nin şemasız yapısına bir disiplin getirerek, verilerinizin "tip güvenli" olmasını sağlar.

Mongoose Şeması ile Temel Veri Doğrulama

Mongoose şemaları, veritabanındaki her bir dokümanın yapısını tanımlar. Temel doğrulama kuralları, alan tanımları içerisinde required, min, max gibi özelliklerle belirlenir. Aşağıdaki örnekte, bir kullanıcı modeli için temel doğrulama kurallarını tanımlıyoruz.

const mongoose = require('mongoose');

const userSchema = new mongoose.Schema({
  username: {
    type: String,
    required: [true, 'Kullanıcı adı zorunludur.'],
    minlength: [3, 'Kullanıcı adı en az 3 karakter olmalıdır.'],
    trim: true
  },
  age: {
    type: Number,
    min: [18, 'Yaş 18\'den küçük olamaz.'],
    max: [99, 'Yaş 99\'dan büyük olamaz.']
  }
});

const User = mongoose.model('User', userSchema);

Bu kodda, required ile verinin boş geçilemeyeceğini, minlength ile metin uzunluğunu, min ve max ile sayısal aralıkları sınırlandırdık. Hata mesajlarını dizi içinde vererek, doğrulama başarısız olduğunda özel mesajlar döndürülmesini sağladık.

Özel Doğrulayıcılar (Custom Validators) Nasıl Yazılır?

Bazen yerleşik kurallar yeterli olmaz. Örneğin, bir e-posta adresinin sadece belirli bir alan adına sahip olması gerektiğini veya karmaşık bir şifre formatını doğrulamak isteyebilirsiniz. Bunun için validate özelliğini kullanırız.

const userSchema = new mongoose.Schema({
  email: {
    type: String,
    validate: {
      validator: function(v) {
        return /^[a-zA-Z0-9._%+-]+@kurumsal\.com$/.test(v);
      },
      message: props => `${props.value} geçerli bir kurumsal e-posta değil!`
    }
  }
});

Burada kullanılan validator fonksiyonu, veri geçerliyse true, değilse false döndürmelidir. Bu yöntem, iş mantığınıza (business logic) özgü kuralları Mongoose seviyesinde uygulamanıza olanak tanır.

Doğrulama Hatalarını Yakalama ve Yönetme

Doğrulama hataları oluştuğunda, Mongoose bir ValidationError fırlatır. Bu hataları düzgün bir şekilde yönetmek, kullanıcı deneyimini artırır. Aşağıdaki örnekte, bir dokümanı kaydederken hataları nasıl yakalayacağımızı görebilirsiniz.

const newUser = new User({ username: 'ab', age: 15 });

newUser.save()
  .then(() => console.log('Kullanıcı başarıyla kaydedildi.'))
  .catch(err => {
    if (err.name === 'ValidationError') {
      for (let field in err.errors) {
        console.error(`Hata: ${err.errors[field].message}`);
      }
    }
  });

Bu kod bloğu, save() işlemi sırasında oluşan hataları filtreler ve her bir alan için tanımladığımız özel hata mesajlarını konsola yazdırır. Üretim ortamında bu mesajları API yanıtı olarak istemciye (frontend) göndermek en iyi pratiktir.

Güvenlik Uyarısı: Mongoose doğrulama katmanı, veritabanı güvenliği için bir "ilk savunma hattı"dır. Ancak, asla sadece istemci tarafındaki doğrulamaya güvenmeyin. Veritabanı seviyesinde doğrulama, uygulama kodunuzdaki hatalı veri girişlerini engellemek için zorunludur.

Doğrulama Yöntemlerinin Karşılaştırılması

Aşağıdaki tablo, Mongoose üzerinde kullanılan farklı doğrulama yöntemlerinin avantaj ve dezavantajlarını özetlemektedir.

Yöntem Avantajı Dezavantajı
Yerleşik (Built-in) Hızlı ve kolay uygulanır. Karmaşık mantıklar için yetersizdir.
Özel (Custom) Sınırsız esneklik sağlar. Daha fazla kod yazımı gerektirir.
Middleware (Pre-save) Birden fazla alanı kontrol eder. Hata yönetimi daha karmaşıktır.

Asenkron Doğrulama İşlemleri

Bazen bir verinin doğruluğunu kontrol etmek için veritabanına tekrar bakmanız gerekebilir (örneğin: kullanıcı adının benzersiz olup olmadığını kontrol etmek). Mongoose, asenkron doğrulayıcıları destekler.

userSchema.path('username').validate(async function(value) {
  const count = await mongoose.models.User.countDocuments({ username: value });
  return count === 0;
}, 'Bu kullanıcı adı zaten alınmış.');

Bu örnekte, async/await yapısı kullanılarak veritabanında aynı kullanıcı adına sahip başka bir kayıt olup olmadığı kontrol edilir. Eğer count sıfırdan büyükse, doğrulama başarısız olur.

Sıkça Sorulan Sorular

Mongoose doğrulaması veritabanı güncellemelerinde çalışır mı?

Varsayılan olarak Mongoose doğrulaması sadece save() metodunda çalışır. findOneAndUpdate veya updateMany gibi işlemlerde doğrulamanın çalışması için runValidators: true seçeneğini eklemeniz gerekir.

Doğrulama hatalarını nasıl özelleştirebilirim?

Her alanın tanımında message özelliğini kullanarak veya validate bloğu içerisindeki message fonksiyonunu kullanarak hata mesajlarını tamamen özelleştirebilirsiniz.

Regex kullanımı doğrulama için yeterli mi?

Regex, format doğrulaması (telefon, e-posta, TC kimlik no) için çok güçlüdür ancak iş mantığı içeren (örneğin "stokta varsa ekle") kontroller için yeterli değildir; bu tür durumlar için fonksiyon tabanlı doğrulayıcılar kullanmalısınız.

Doğrulama başarısız olduğunda veritabanına yazılır mı?

Hayır, Mongoose doğrulama başarısız olursa veriyi veritabanına göndermez ve bir hata fırlatır. Bu, veritabanınızın her zaman temiz kalmasını sağlar.

Performans üzerinde olumsuz etkisi var mıdır?

Çok fazla asenkron doğrulayıcı kullanmak, veritabanı sorgu sayısını artıracağı için performansı etkileyebilir. Bu nedenle kritik olmayan kontrolleri uygulama katmanında yapmanız önerilir.

İleri Seviye Doğrulama Stratejileri ve Veri Bütünlüğü

Mongoose şemalarında yerleşik olarak bulunan doğrulama kuralları, uygulama katmanında veri bütünlüğünü sağlamak için harika bir başlangıçtır. Ancak, karmaşık iş mantığı (business logic) gerektiren durumlarda sadece şema bazlı doğrulamalar yetersiz kalabilir. Özellikle veritabanı seviyesindeki ilişkisel kontrollerde veya harici servislerden gelen verilerin doğrulanmasında daha modüler bir yapıya ihtiyaç duyarsınız.

Middleware Kullanarak Veri Sanitizasyonu ve Doğrulama

Mongoose pre('save') middleware yapısı, veritabanına yazılmadan önce veriyi manipüle etmek veya ek kontroller yapmak için en ideal noktadır. Örneğin, bir kullanıcının girdiği veriyi kaydetmeden önce trim etmek veya belirli bir formatta normalize etmek, veri kirliliğini önler.


userSchema.pre('save', function(next) {
  if (this.isModified('email')) {
    this.email = this.email.toLowerCase().trim();
  }
  
  // Karmaşık iş kuralı: Eğer kullanıcı 'admin' ise, özel bir onay kodu zorunlu olsun
  if (this.role === 'admin' && !this.adminCode) {
    return next(new Error('Admin rolü için adminCode zorunludur.'));
  }
  
  next();
});

Doğrulama Süreçlerinde Performans Optimizasyonu

Veri doğrulama, özellikle yüksek trafikli uygulamalarda işlemci ve veritabanı kaynaklarını tüketebilir. Mongoose ile çalışırken performans kayıplarını minimize etmek için şu stratejileri izleyebilirsiniz:

  • Gereksiz Doğrulamalardan Kaçının: Sadece değişen alanları doğrulamak için isModified() metodunu kullanın.
  • Asenkron Doğrulamaları Optimize Edin: Veritabanına sorgu atan asenkron doğrulayıcıları, sadece kritik alanlar için kullanın. Mümkünse bu kontrolleri uygulama katmanında (Controller) önceden yapın.
  • İndeksleme: unique: true gibi kurallar veritabanı seviyesinde indeks oluşturur. Bu, doğrulama hızını artırırken, aynı zamanda veritabanı yazma performansını etkileyebilir. Çok sık güncellenen alanlarda bu seçeneği dikkatli kullanın.

Hata Ayıklama (Debugging) ve Hata Mesajlarını Gruplama

Kullanıcıya tek seferde tüm hataları göstermek, kullanıcı deneyimini (UX) doğrudan iyileştirir. Mongoose varsayılan olarak ilk hatada durabilir veya tüm hataları bir nesne içinde dönebilir. Aşağıdaki yöntemle hataları daha okunabilir bir formata dönüştürebilirsiniz:


try {
  await user.save();
} catch (error) {
  if (error.name === 'ValidationError') {
    const messages = Object.values(error.errors).map(err => err.message);
    console.error('Doğrulama Hataları:', messages);
    // İstemciye 400 Bad Request ile hataları döndürün
  }
}
İpucu: Büyük ölçekli projelerde, Mongoose doğrulama kurallarını şema dosyasında tutmak yerine, bu kuralları birer "Validator" fonksiyonu olarak ayrı bir klasörde (örneğin: /validators) tutmak, kodunuzun test edilebilirliğini ve okunabilirliğini artıracaktır.

Sonuç

Node.js ve Mongoose kullanarak veri doğrulama yapmak, uygulamanızın veri kalitesini korumak için vazgeçilmez bir süreçtir. Bu rehberde, temel doğrulama kurallarından asenkron kontrollere kadar profesyonel bir yaklaşımı adım adım inceledik. Bir sonraki aşamada, verilerinizi daha güvenli hale getirmek için Joi veya Zod gibi şema doğrulama kütüphanelerini Mongoose ile birlikte nasıl entegre edebileceğinizi araştırmanızı öneririm.

Sorumluluk Reddi: Bu makalede paylaşılan kod örnekleri eğitim amaçlıdır. Uygulamanızın üretim ortamına geçmeden önce, tüm kullanıcı girişlerini sanitize etmeyi (temizlemeyi) ve güvenlik açıklarına karşı (XSS, Injection) gerekli önlemleri almayı unutmayın. Veritabanı güvenliği, sadece doğrulama ile değil, doğru konfigürasyon ve yetkilendirme ile sağlanır.

Bu yazıya tepkinizi paylaşın:
Kerem Tekin

Teknik rehberler ve dijital araçların verimli kullanımı konusunda uzmanlaşmış bir editörüm. Karmaşık teknolojik süreçleri, herkesin kolayca uygulayabileceği rehberlere dönüştürerek zaman tasarrufu sağlamayı hedefliyorum.

Yorumlar (0)

Yorum Yaz