MongoDB'de bir koleksiyona kural koymak için schema validation kullanılır: koleksiyonu oluştururken validator seçeneğine bir $jsonSchema belgesi verirsiniz veya mevcut koleksiyona collMod komutuyla eklersiniz. Bundan sonra kurala uymayan ekleme ve güncellemeler varsayılan olarak Document failed validation hatasıyla reddedilir. Kuralın mevcut belgelere nasıl uygulanacağını validationLevel, ihlalde ne olacağını validationAction belirler.
Bu yazıda $jsonSchema anahtar kelimelerini, hata çıktısının nasıl okunacağını, strict, moderate ve MongoDB 9.0 ile gelen constraint seviyelerini, error, warn ve errorAndLog eylemlerini, kurala uymayan eski belgeleri bulmayı ve doğrulamayı baypas etmeyi anlatıyoruz. Ne zaman katı bir yapıya ihtiyaç duyacağınıza karar vermek için önce veri modelleme yazısını okumanız faydalı olur.
Ne zaman schema validation kullanmalı?

MongoDB esnek şema modeli kullanır: varsayılan olarak bir koleksiyondaki belgelerin aynı alanlara veya türlere sahip olması gerekmez. Belgelere göre doğrulama en çok, veri yapısı oturmuş bir uygulamada işe yarar ve kurallar her alanı kapsamak zorunda değildir. Tipik senaryolar şunlardır:
- Bir
start_datealanının metin değil, yalnızca tarih saklamasını sağlamak. - Bir alanın yalnızca izin verilen değerleri (örneğin kabul edilen kart türleri) içermesini sağlamak.
- Not ortalaması gibi bir alanın her zaman pozitif bir sayı olmasını sağlayarak veri girişi hatalarını önlemek.
Doğrulama kuralları eklendikten sonra bütün eklemeler kurala uymak zorundadır. Mevcut belgelerin ve güncellemelerin nasıl ele alınacağını ise doğrulama seviyesi belirler.
Doğrulamalı koleksiyon oluşturmak
db.createCollection( "urunler", {
validator: { $jsonSchema: {
bsonType: "object",
title: "Ürün doğrulaması",
required: [ "ad", "fiyat", "kategori" ],
properties: {
ad: { bsonType: "string", minLength: 2,
description: "en az 2 karakterlik metin olmalı ve zorunludur" },
fiyat: { bsonType: [ "double", "decimal" ], minimum: 0,
description: "sıfır veya pozitif sayı olmalı ve zorunludur" },
kategori: { enum: [ "elektronik", "kirtasiye", "kitap" ],
description: "izin verilen kategorilerden biri olmalı" },
stok: { bsonType: "int", minimum: 0,
description: "varsa sıfır veya pozitif tamsayı olmalı" },
etiketler: { bsonType: "array", maxItems: 10, uniqueItems: true,
items: { bsonType: "string" } }
}
} },
validationLevel: "strict",
validationAction: "error"
} )Bu kural şunları zorunlu kılar: ad, fiyat ve kategori her belgede bulunmalı; ad en az iki karakterlik bir metin, fiyat sıfır veya pozitif bir double ya da decimal olmalı; kategori yalnızca listedeki üç değerden biri olabilir. stok ve etiketler zorunlu değildir; ama varsa kurallara uymaları gerekir. validationLevel ve validationAction burada zaten varsayılan değerleriyle yazıldı; açık yazmak kuralı okuyan herkes için niyeti netleştirir.
Tamsayı alanlarında tür tuzağı
stok alanını bsonType: "int" olarak tanımladık. mongosh'ta 32 bitlik tamsayıyı açıkça belirtmek için Int32() yapıcısı kullanılır; belgelerdeki baypas örneği de yıl alanını Int32( 2016 ) olarak yazar. Sayının türünden emin değilseniz kuralda birden fazla türe izin verebilirsiniz (örneğin [ "int", "long" ]). JSON Schema'daki type: "integer" desteklenmez; bunun yerine bsonType ile int veya long kullanılmalıdır.
db.urunler.insertOne( { ad: "Defter", fiyat: 45.5, kategori: "kirtasiye", stok: Int32( 120 ) } )
// çıktı: { acknowledged: true, insertedId: ObjectId("6304f4651e52f124b84479ba") }
db.urunler.insertOne( { ad: "K", fiyat: -5, kategori: "oyuncak" } )
// çıktı: MongoServerError: Document failed validationİlk ekleme kurallara uyduğu için başarılı olur ve insertOne her zamanki gibi onay ile eklenen belgenin kimliğini döndürür (kimlik değeri her eklemede farklıdır). İkinci belge üç kuralı birden ihlal eder: ad çok kısa, fiyat negatif ve kategori listede yok.
Hata çıktısını okumak
Hata mesajının Additional information bölümü hangi kuralın neden sağlanmadığını ayrıntılı olarak listeler. Belgelerdeki örneklere göre yapı şöyledir:
failingDocumentId: reddedilen belgenin_iddeğeri.details.operatorName: kuralın türü; JSON Schema için$jsonSchema, sorgu operatörü kuralları için$exprgibi.schemaRulesNotSatisfied: sağlanmayan kuralların listesi.propertiesaltında her alan içinpropertyName,descriptionve hangi anahtar kelimenin (minLength,enum,patterngibi) neden başarısız olduğu yer alır.reasonveconsideredValue: kuralın neden sağlanmadığı ve hangi değerin incelendiği; örneğinvalue was not found in enumveyaspecified string length was not satisfied.missingProperties:requiredlistesinde olup belgede bulunmayan alanlar.
$jsonSchema anahtar kelimeleri
MongoDB, JSON Schema taslak 4 sürümünü bazı farklarla destekler ve en önemli ek olarak bsonType anahtar kelimesini getirir. bsonType, $type sorgu operatörünün kabul ettiği dize takma adlarını (string, int, double, decimal, date, objectId, bool, array, object ve diğerleri) kullanır.
| Anahtar kelime | Uygulandığı tür | Görevi |
|---|---|---|
| bsonType | Tümü | Alanın BSON türü (tek değer veya dizi) |
| required | Nesne | Bulunması zorunlu alanlar |
| properties | Nesne | Her alan için alt şema |
| additionalProperties | Nesne | false ise listede olmayan alanlara izin verilmez (varsayılan true) |
| enum | Tümü | İzin verilen değerlerin listesi |
| minimum, maximum | Sayı | Alt ve üst sınır |
| minLength, maxLength | Metin | Uzunluk sınırları |
| pattern | Metin | Uyması gereken düzenli ifade |
| items, minItems, maxItems, uniqueItems | Dizi | Eleman şeması, eleman sayısı ve benzersizlik |
| oneOf, anyOf, allOf, not | Tümü | Şemaları birleştirme |
| title, description | Yok | Açıklama; doğrulamayı etkilemez |
Desteklenmeyenler de bilinmeli: $ref, $schema, default, definitions, format ve id anahtar kelimeleri, integer türü, JSON Reference ve JSON Pointer gibi bağlantı özellikleri ile bilinmeyen anahtar kelimeler. Başka bir projeden kopyaladığınız JSON Schema dosyasında format: "email" veya default varsa onları çıkarmanız gerekir.
Doğrulama seviyesi: validationLevel

| Seviye | Davranış |
|---|---|
| strict (varsayılan) | Bütün eklemelere ve güncellemelere aynı kurallar uygulanır |
| moderate | Eklemeler ve zaten geçerli olan belgelerin güncellemeleri doğrulanır; geçersiz eski belgelerin güncellemeleri doğrulanmaz |
| constraint (9.0) | Bütün eklemeler ve güncellemeler doğrulanır ve koleksiyondaki her belgenin kurala uyduğu garanti edilir |
strict ve moderate seviyelerinde MongoDB, kuralı eklediğiniz veya değiştirdiğiniz anda koleksiyondaki eski belgeleri geriye dönük olarak denetlemez. strict seviyesinde geçersiz bir eski belgeyi güncellemeye çalışırsanız, güncellemenin kendisi ihlal getirmese bile işlem başarısız olur; önce belgeyi kurala uygun hale getirmeniz gerekir. moderate seviyesi ise eski verinin kademeli temizlendiği geçiş dönemleri için uygundur.
constraint seviyesi (MongoDB 9.0 ile yeni)
MongoDB 9.0 sürüm notları constraint seviyesini yeni özellik olarak listeler. Bu seviyede koleksiyon, seviyeyi ayarlamadan önce var olan geçersiz belgeleri de içeremez. Ek kısıtları vardır: validationAction değeri error veya errorAndLog olmalıdır; seviye constraint iken kurallar doğrudan değiştirilemez; doğrulama baypas edilemez. Mevcut bir koleksiyonu bu seviyeye taşımak iki adımlıdır:
// 1) Hazırlık: baypası engeller ve validator değişikliğini durdurur
db.runCommand( { collMod: "urunler", prepareConstraintValidationLevel: true } )
// 2) Seviyeyi yükselt: bütün belgeler taranır, ihlal varsa komut başarısız olur
db.runCommand( { collMod: "urunler", validationLevel: "constraint" } )Örnekteki koleksiyonun validationAction değeri zaten error olduğu için ikinci komutta yalnızca seviyeyi değiştirdik. Koleksiyonun seviyesi strict değilse önce strict yapılmalıdır. Seviyeyi yükselttiğiniz collMod işleminde validator değiştirilemez; kuralları önceden ayarlamış olmalısınız. Belgelere göre seviye constraint yapılırken bütün belgeler taranır ve büyük koleksiyonlarda bu tarama hesaplama açısından pahalı olabilir. Koleksiyonu oluştururken doğrudan constraint verirseniz hazırlık adımına gerek kalmaz. Kuralları sonradan değiştirmek için seviyeyi strict yapıp kuralı güncellemeli ve yeniden constraint seviyesine çıkmalısınız. 9.0'ın diğer değişiklikleri için MongoDB 9.0 yenilikleri yazısına bakın.
Doğrulama eylemi: validationAction
| Eylem | Davranış |
|---|---|
| error (varsayılan) | Kurala uymayan ekleme veya güncelleme reddedilir |
| warn | İşleme izin verilir, ihlal MongoDB loguna yazılır |
| errorAndLog (8.1) | İşlem reddedilir ve hata mongod log dosyasına da yazılır |
warn eylemi, şemadan önceki dönemden kalan belgeleri içeren bir veri taşıma işi gibi durumlarda işe yarar: işlem sürer, ama ihlaller Document would fail validation mesajıyla loga düşer. Logları mongosh içinden db.adminCommand( { getLog: "global" } ) ile okuyabilirsiniz. Log yönetimi için yavaş sorgu ve log yazısına göz atabilirsiniz.
Mevcut koleksiyona kural eklemek veya kuralı değiştirmek
Kural eklemek de değiştirmek de collMod komutuyla yapılır; yeni validator belgesi eskisinin yerine geçer, yani yalnızca değişen kısmı değil kuralın tamamını göndermelisiniz:
db.runCommand( {
collMod: "urunler",
validator: { $jsonSchema: {
bsonType: "object",
required: [ "ad", "fiyat", "kategori", "sku" ],
properties: {
ad: { bsonType: "string", minLength: 2 },
fiyat: { bsonType: [ "double", "decimal" ], minimum: 0 },
kategori: { enum: [ "elektronik", "kirtasiye", "kitap" ] },
stok: { bsonType: "int", minimum: 0 },
sku: { bsonType: "string", pattern: "^[A-Z]{3}-[0-9]{4}$",
description: "ABC-1234 biçiminde olmalı" }
}
} },
validationLevel: "moderate"
} )Bu örnekte önceki kuralları koruyup yeni zorunlu sku alanını ekledik (kısalık için açıklamaları ve etiketler kuralını çıkardık; gerçek kullanımda korumak istediğiniz her kuralı yeniden yazmalısınız) ve eski belgeler henüz bu alana sahip olmadığı için seviyeyi geçici olarak moderate yaptık. Böylece yeni ürünler kurala uymak zorundadır, ama alanı olmayan eski ürünlerin güncellenmesi engellenmez. Eski belgeleri temizledikten sonra seviyeyi tekrar strict yapabilirsiniz.
Koleksiyonun mevcut kurallarını görmek için db.getCollectionInfos( { name: "urunler" } )[0].options.validator veya listCollections komutunu kullanabilirsiniz. validationAction ve validationLevel açıkça ayarlanmamışsa db.getCollectionInfos() çıktısında görünmez.
Kurala uymayan belgeleri bulmak
$jsonSchema yalnızca doğrulamada değil sorgularda da kullanılabilir. Şemayı bir değişkene koyup $nor ile birlikte kullanırsanız kurala uymayan belgeleri bulursunuz:
let urunSemasi = { $jsonSchema: {
required: [ "ad", "fiyat", "kategori" ],
properties: { fiyat: { bsonType: [ "double", "decimal" ], minimum: 0 } }
} }
db.urunler.find( { $nor: [ urunSemasi ] } ) // kurala uymayanlar
db.urunler.updateMany( { $nor: [ urunSemasi ] }, { $set: { gecersiz: true } } )
db.urunler.find( urunSemasi ) // kurala uyanlarBu yöntem kuralı collMod ile sıkılaştırmadan önce ne kadar eski belgenin etkileneceğini ölçmenizi sağlar. warn eylemiyle çalışan koleksiyonları düzenli olarak temizlemek için de kullanılır.
Sorgu operatörleriyle doğrulama
Bir alanın değeri başka bir alana bağlıysa JSON Schema yetmez; $expr ile alanları karşılaştıran bir doğrulama yazabilirsiniz. Belgelerdeki örnek KDV dahil toplamın, toplam ile KDV oranından hesaplanan değere eşit olmasını zorlar:
db.createCollection( "faturalar", {
validator: { $expr: {
$eq: [ "$kdvDahil", { $multiply: [ "$tutar", { $sum: [ 1, "$kdvOrani" ] } ] } ]
} }
} )İki yaklaşımı $and ile birleştirebilirsiniz. validator içinde $near, $nearSphere, $text, $where ve $function içeren $expr kullanılamaz. Ayrıca admin, local ve config veritabanlarındaki koleksiyonlara ve sistem koleksiyonlarına doğrulama eklenemez.
İnce noktalar

- additionalProperties: false ve _id: her belgede otomatik bir
_idbulunduğu içinadditionalProperties: falsekullanıyorsanız_idalanınıpropertiesiçine eklemelisiniz; aksi halde hiçbir belge kabul edilmez. - null ile eksik alan farkı: bir alanın türünü
stringolarak sınırladıysanıznulldeğer reddedilir; izin vermek içinbsonType: [ "null", "string" ]yazın. Belgede hiç bulunmayan bir alan ise doğrulanmaz. - Farklı belge türleri: aynı koleksiyonda müşteri ve hesap gibi farklı yapıda belgeler tutuyorsanız her tür için bir şema tanımlayıp
oneOfile birleştirebilirsiniz. - $out ve $merge: hedef koleksiyonda
validationActionerrorise aggregation ile yazılan geçersiz belgeler de reddedilir; ayrıntılar $out ve $merge yazısında.
Doğrulamayı baypas etmek
Eski bir yedeği yeni kurallara sahip bir koleksiyona geri yüklemek gibi durumlarda doğrulamayı tek bir işlem için atlayabilirsiniz. Baypas işlem başına yapılır ve insert, update, findAndModify, applyOps, mapReduce komutları ile $out ve $merge aşamalarında desteklenir.
db.runCommand( {
insert: "urunler",
documents: [ { ad: "Eski Kayıt", fiyat: -1, kategori: "arsiv" } ],
bypassDocumentValidation: true
} )Erişim denetimi açık bir sunucuda bunun için kullanıcının bypassDocumentValidation eylemine sahip olması gerekir; yerleşik dbAdmin ve restore rolleri bu eylemi içerir (roller için kullanıcı ve rol yönetimi yazısına bakın). Baypasla eklenen geçersiz bir belgenin sonraki güncellemeleri de ya baypas etmeli ya da belgeyi geçerli hale getirmelidir. Koleksiyonun seviyesi constraint ise veya prepareConstraintValidationLevel açıksa, belge geçerli olsa bile bypassDocumentValidation: true içeren her yazma BadValue hatasıyla reddedilir.
Sık yapılan hatalar
- type: integer yazmak: desteklenmez;
bsonType: "int"veya"long"kullanın. - additionalProperties: false ile _id'yi unutmak: bütün eklemeler reddedilir.
- collMod ile yalnızca yeni alanı göndermek: yeni validator eskisinin yerine geçer; tüm kuralı gönderin.
- Kural ekleyince eski verinin denetlendiğini sanmak:
strictvemoderategeriye dönük denetim yapmaz;$norsorgusuyla eski belgeleri kontrol edin. - Hata metnini ayrıştırmak: çıktı biçimi değişebilir.
- Desteklenmeyen anahtar kelimeler:
format,default,$refiçeren hazır şemalar olduğu gibi çalışmaz.
Sık Sorulan Sorular
Schema validation performansı etkiler mi?
Doğrulama ekleme ve güncelleme sırasında yapılır; okuma sorgularına bir kural uygulanmaz. Belgelerin performansla ilgili özel olarak uyardığı nokta, constraint seviyesine geçerken bütün koleksiyonun taranmasının büyük koleksiyonlarda pahalı olabileceğidir.
Uygulamada doğrulama yapıyorsam veritabanında da gerekir mi?
İkisi farklı katmanlardır. Belgelerdeki kullanım senaryoları, birden fazla uygulamanın aynı koleksiyona bağlandığı durumlarda tutarlı türlerin beklenmedik değerleri önlediğini vurgular. Veritabanı kuralı, hangi istemci yazarsa yazsın son savunma hattıdır.
Kuralı geçici olarak kapatabilir miyim?
collMod ile validationAction değerini warn yapabilir veya tek işlemler için bypassDocumentValidation kullanabilirsiniz. constraint seviyesindeki koleksiyonlarda baypas mümkün değildir.
Hangi belgelerin geçersiz olduğunu toplu görebilir miyim?
Evet; şemayı $nor içinde kullanan bir find() sorgusu kurala uymayan bütün belgeleri döndürür. Bulduğunuz belgeleri önce updateMany() ile işaretleyip ardından tek tek düzeltebilir veya silebilirsiniz.
Marka adları sahiplerine aittir. Bu yazı bağımsız bir teknik rehberdir; adı geçen kuruluşlarla bayilik veya ortaklık ilişkisi bulunduğu anlamına gelmez.
İlgili içerikler: MongoDB öğrenme rehberi · Veri modelleme · Koleksiyon oluşturma · BSON veri tipleri · insertOne ve insertMany · MongoDB 9.0 yenilikleri