MongoDB find sorgusu, koleksiyondaki belgeleri alan değerlerine göre filtrelemek için kullanılır. Eşitlik sorgularında doğrudan alan ve değer yazabilir, karşılaştırma gerektiğinde $gt, $gte, $lt, $lte, $ne ve $in gibi sorgu operatörlerinden yararlanabilirsin.
SQL bilgisi olanlar için filtre bölümü WHERE koşuluna benzer. MongoDB’de bu koşullar, JavaScript nesne yazımına benzeyen sorgu belgeleriyle ifade edilir.
Koleksiyon, belge, find() ve findOne() nasıl ayrılır?
MongoDB’de koleksiyon, ilişkisel veritabanındaki tabloya; belge ise tablodaki satıra benzetilebilir. Belge, alan ve değer çiftlerinden oluşur ve iç içe belgeler ile diziler barındırabilir. Aşağıdaki yazım JSON’a benzese de MongoDB verileri BSON belgeleri olarak saklar. BSON, JSON yapısına ek veri türleri sunan ikili bir veri biçimidir. MongoDB belgelerinde BSON ve belge yapısı ayrıntılı biçimde açıklanır.
db.ogrenciler.insertMany([
{ _id: 1, ad: 'Ayşe', sinif: 1, puan: 85, dersler: ['Matematik', 'Fizik'] },
{ _id: 2, ad: 'Berk', sinif: 2, puan: 75, dersler: ['Biyoloji', 'Kimya'] },
{ _id: 3, ad: 'Cem', sinif: 1, puan: 90, dersler: ['Matematik', 'Kimya'] },
{ _id: 4, ad: 'Deniz', sinif: 3, puan: 65, dersler: ['Fizik', 'Biyoloji'] }
])
find({}), boş filtre belgesi kullandığı için koleksiyondaki tüm belgeleri seçer. find() teknik olarak eşleşen belgeleri sağlayan bir imleç döndürür, mongosh ise bu sonuçları ekranda gösterir.
db.ogrenciler.find({})
[
{ _id: 1, ad: 'Ayşe', sinif: 1, puan: 85, dersler: ['Matematik', 'Fizik'] },
{ _id: 2, ad: 'Berk', sinif: 2, puan: 75, dersler: ['Biyoloji', 'Kimya'] },
{ _id: 3, ad: 'Cem', sinif: 1, puan: 90, dersler: ['Matematik', 'Kimya'] },
{ _id: 4, ad: 'Deniz', sinif: 3, puan: 65, dersler: ['Fizik', 'Biyoloji'] }
]
findOne() ise sorgu koşulunu karşılayan tek bir belge döndürür. Bu örnekte ad alanı Ayşe olan belge seçilir. Çıktıda, sorguda açıkça gizlenmediği için _id alanı da görünür.
db.ogrenciler.findOne({ ad: 'Ayşe' })
{ _id: 1, ad: 'Ayşe', sinif: 1, puan: 85, dersler: ['Matematik', 'Fizik'] }
Eşitlik ve karşılaştırma filtreleri nasıl yazılır?

Temel eşitlik sorgusunda alanın karşısına doğrudan beklenen değeri yazarsın. Örneğin { sinif: 1 }, sınıfı 1 olan Ayşe ve Cem belgelerini; { ad: 'Ayşe' } ise yalnızca Ayşe belgesini seçer.
db.ogrenciler.find({ sinif: 1 })
db.ogrenciler.find({ ad: 'Ayşe' })
Karşılaştırma operatörleri, SQL’deki WHERE puan > 70 gibi koşulların MongoDB sorgu biçimindeki karşılıklarını oluşturur. MongoDB karşılaştırma operatörleri belirli BSON türleriyle çalıştığı için puan alanını 85 sayısı olarak saklamak gerekir. Değer '85' metni olarak tutulursa sayısal karşılaştırma beklenen sonucu vermeyebilir.
Aynı alana birden fazla koşul yazarken alanı iki kez tekrarlama. JavaScript nesne yazımında aynı anahtarın önceki değeri kaybolabileceği için iki koşulu aynı nesne içinde birleştir:
| Operatör | Anlam | Sorgu örneği | Dönen belgeler |
|---|---|---|---|
$gt ve $lt |
70’ten büyük ve 90’dan küçük | { puan: { $gt: 70, $lt: 90 } } |
_id: 1, Ayşe, 85_id: 2, Berk, 75 |
$gte |
80 veya daha büyük | { puan: { $gte: 80 } } |
_id: 1, Ayşe, 85_id: 3, Cem, 90 |
$ne |
1’e eşit olmayan | { sinif: { $ne: 1 } } |
_id: 2, Berk, 75_id: 4, Deniz, 65 |
$in |
Listedeki değerlerden biri | { ad: { $in: ['Ayşe', 'Deniz'] } } |
_id: 1, Ayşe, 85_id: 4, Deniz, 65 |
Birden fazla koşul ve sık yapılan hatalar nasıl yönetilir?
Bir sorgu nesnesinde farklı alanları virgülle sıraladığında, MongoDB bu koşulları örtük bir AND ilişkisiyle birleştirir. $or ise verilen koşullardan en az birini karşılayan belgeleri seçer.
Aşağıdaki örnekleri boş bir ogrenciler koleksiyonunda deneyebilirsin. Süslü parantezler alan ve değer çiftlerinden oluşan belgeyi, köşeli parantezler ise listeyi gösterir.
db.ogrenciler.insertMany([
{ _id: 1, ad: "Ayşe", sinif: 1, puan: 85, dersler: ["Matematik"] },
{ _id: 2, ad: "Berk", sinif: 2, puan: 65, dersler: ["Fizik"] },
{ _id: 3, ad: "Cem", sinif: 1, puan: 95, dersler: ["Matematik"] },
{ _id: 4, ad: "Deniz", sinif: 3, puan: 75, dersler: ["Fizik"] }
])
Şu sorgu, hem birinci sınıfta olan hem de puanı en az 80 olan öğrencileri getirir:
db.ogrenciler.find({ sinif: 1, puan: { $gte: 80 } })
// Dönen belgeler:
{ _id: 1, ad: "Ayşe", sinif: 1, puan: 85, dersler: ["Matematik"] }
{ _id: 3, ad: "Cem", sinif: 1, puan: 95, dersler: ["Matematik"] }
$or ile koşulları bir liste içinde belirtirsin. Aşağıdaki sorgu, üçüncü sınıfta olan veya puanı en az 90 olan öğrencileri seçer:
db.ogrenciler.find({
$or: [{ sinif: 3 }, { puan: { $gte: 90 } }]
})
// Dönen belgeler:
{ _id: 3, ad: "Cem", sinif: 1, puan: 95, dersler: ["Matematik"] }
{ _id: 4, ad: "Deniz", sinif: 3, puan: 75, dersler: ["Fizik"] }
Aynı alana alt ve üst sınır koyarken operatörleri tek bir puan nesnesinde birleştir:
db.ogrenciler.find({ puan: { $gte: 70, $lt: 90 } })
// Dönen belgeler:
{ _id: 1, ad: "Ayşe", sinif: 1, puan: 85, dersler: ["Matematik"] }
{ _id: 4, ad: "Deniz", sinif: 3, puan: 75, dersler: ["Fizik"] }
{ puan: { $gte: 70 }, puan: { $lt: 90 } } yazımında aynı anahtar tekrarlanır; nesne oluşturulurken ilk değer sonrakinin üzerine yazılmasıyla kaybolabilir. Ayrıca sayısal 85 ile metin olan "85" farklı türlerdir: Sayısal bir $gte karşılaştırması metin olarak saklanan puanı eşleştirmez.
Beklemediğin bir sonuçla karşılaşırsan şu kontrolleri yapabilirsin:
- Alan adını belgelerdeki yazımla karşılaştır.
- Değerin sayı mı, metin mi olduğunu kontrol et.
- Operatörlerin doğru alanın içinde bulunduğunu ve anahtarların tekrarlanmadığını incele.
- Dönen belgeleri koşullarla karşılaştır.
Projeksiyonla yalnızca gerekli alanlar nasıl seçilir?

find() içindeki ikinci nesne projeksiyondur ve sonuç belgelerinde hangi alanların gösterileceğini belirler. İlk nesnedeki {} tüm belgeleri seçerken, ikinci nesnede 1 alanı dahil eder, 0 ise hariç tutar.
Örneğin yalnızca ad ve puanı almak, _id alanını da gizlemek için şu sorguyu kullanabilirsin:
db.ogrenciler.find({}, { ad: 1, puan: 1, _id: 0 })
// Dönen belgeler:
{ ad: "Ayşe", puan: 85 }
{ ad: "Berk", puan: 65 }
{ ad: "Cem", puan: 95 }
{ ad: "Deniz", puan: 75 }
_id alanını projeksiyonda belirtmezsen, dahil edilen diğer alanlarla birlikte o da döner:
db.ogrenciler.find({}, { ad: 1, puan: 1 })
// Dönen belgeler:
{ _id: 1, ad: "Ayşe", puan: 85 }
{ _id: 2, ad: "Berk", puan: 65 }
{ _id: 3, ad: "Cem", puan: 95 }
{ _id: 4, ad: "Deniz", puan: 75 }
Alanları tek tek seçmek yerine yalnızca dersler alanını da dışarıda bırakabilirsin:
db.ogrenciler.find({}, { dersler: 0 })
// Dönen belgeler:
{ _id: 1, ad: "Ayşe", sinif: 1, puan: 85 }
{ _id: 2, ad: "Berk", sinif: 2, puan: 65 }
{ _id: 3, ad: "Cem", sinif: 1, puan: 95 }
{ _id: 4, ad: "Deniz", sinif: 3, puan: 75 }
Aynı projeksiyonda alan dahil etme ve hariç tutma genel olarak birleştirilemez. _id istisnadır; diğer alanları dahil ederken onu 0 ile gizleyebilirsin.
| Projeksiyon | Durum |
|---|---|
{ ad: 1, puan: 1, dersler: 0 } | Geçersiz: Dahil etme ile hariç tutma karışıyor. |
{ ad: 1, puan: 1, _id: 0 } | Geçerli: _id istisnası kullanılıyor. |
{ dersler: 0 } | Geçerli: Belirtilen alan hariç tutuluyor. |
sort() ve limit() sonuçları nasıl düzenler?
sort() sonuçları belirli bir alana göre sıralar, limit() ise sıralanmış sonuçlardan döndürülecek belge sayısını sınırlar. Aşağıdaki sorgu, ogrenciler koleksiyonundaki belgeleri puanı yüksekten düşüğe sıralar ve ilk iki belgeyi gösterir. find() içindeki boş filtre, belirli bir koşul uygulamadan koleksiyondaki belgeleri seçer.
db.ogrenciler.find(
{},
{ ad: 1, puan: 1, _id: 0 }
).sort({ puan: -1 }).limit(2)
Bu sorgu, puanı 92 olan Cem ile puanı 88 olan Ayşe belgelerini bu sırayla döndürür:
[
{ ad: 'Cem', puan: 92 },
{ ad: 'Ayşe', puan: 88 }
]
sort({ puan: 1 }) puanları artan sırada, sort({ puan: -1 }) ise azalan sırada düzenler. SQL tarafında bunun karşılığı ORDER BY puan ASC veya ORDER BY puan DESC ifadesidir. limit(2) de SQL'deki LIMIT 2 kullanımına benzer.
limit() filtre koşulunu değiştirmez. Puanı belirli bir aralıkta olan belgeleri seçiyorsan bu belgeler yine aynı filtreyle belirlenir, ancak sonuçların yalnızca belirlediğin kadarı gösterilir. sort() ile limit() zincirlenerek önce hangi belgelerin öne çıkacağı, ardından kaç belgenin döneceği belirlenebilir.
Kullanıcı girdisi sorgu enjeksiyonuna karşı nasıl işlenir?
Uygulama kodunda kullanıcıdan gelen bir nesneyi doğrudan find() içine vermek güvenli değildir. Örneğin uygulama puan alanında sayı beklerken kullanıcı { puan: { $gte: 0 } } biçiminde bir nesne gönderirse, MongoDB bu yapıyı sıradan bir değer yerine sorgu operatörü olarak yorumlayabilir ve beklenmeyen belgeleri eşleştirebilir. Bu nedenle sorgu nesnesi, istemciden gelen veri olduğu gibi kullanılmadan uygulama tarafından oluşturulmalıdır.
- Sorgulanabilecek alanları sabit bir izin listesiyle sınırla. Kullanıcının istediği alan adını doğrudan sorgu anahtarı olarak kullanma.
- Puan gibi alanlarda beklenen veri türünü kontrol et. Değer sayı olmalıysa uygun türe dönüştür veya dönüştürülemeyen girdiyi reddet.
- Kullanıcının gönderdiği operatörleri doğrudan çalıştırma. Örneğin
minPuanseçeneğini uygulama içinde açıkça$gteoperatörüne eşle. - İzin verilen operatörleri ayrı bir listede tanımla ve bunun dışındaki anahtarları kabul etme.
- Filtreyi istemciden hazır olarak almak yerine, doğrulanmış değerlerden sunucu tarafında oluştur.
Bu makaledeki mongosh filtreleri, öğrenme amacıyla sabit veriler üzerinden çalışır. Gerçek bir uygulamada veri türü kontrolü, alan ve operatör izinleri ile sorgu oluşturma kuralları ayrıca kurulmalıdır.
Sık Sorulan Sorular
MongoDB’de find() ile findOne() arasındaki temel fark nedir?
find() eşleşen belgeler için bir cursor döndürür ve birden fazla sonucu işlemeye uygundur, findOne() ise koşulu karşılayan tek bir belge döndürür. findOne() sonucunda belge bulunamazsa null dönebilir.
Aynı alanda $gte ve $lt koşulları nasıl birlikte yazılır?
Aynı alana ait $gte ve $lt koşulları, alanın değerinde iki operatör bulunan tek bir nesne içinde birlikte yazılır: { puan: { $gte: 50, $lt: 90 } }. Bu filtre 50 ve üzerindeki, 90'dan küçük puanları seçer.
MongoDB projeksiyonunda _id alanı neden görünür ve nasıl gizlenir?
_id alanı, projeksiyonda başka alanları dahil etsen bile varsayılan olarak sonuçta yer alır. Görünmesini istemiyorsan projeksiyon nesnesinde _id: 0 yazarak bu alanı açıkça hariç tutabilirsin.
sort() ve limit() MongoDB sorgusunda ne işe yarar?
sort() belgeleri belirli bir alana göre artan veya azalan sıraya dizer, limit() ise sonuç kümesinden döndürülecek belge sayısını sınırlar. Birlikte kullanıldıklarında puanı en yüksek birkaç belgeyi veya en düşük birkaç belgeyi seçmek gibi işlemler yapılabilir.
Kullanıcı girdisi MongoDB sorgu nesnesine neden doğrudan eklenmemelidir?
Kullanıcı girdisi doğrudan sorgu nesnesine eklenirse, beklenen bir değer yerine sorgu operatörü içeren bir nesne gönderilebilir ve filtre planlanandan farklı çalışabilir. Alan, veri türü ve operatör kontrolleri yapıldıktan sonra sorguyu uygulama kodunun oluşturması bu riski azaltır.
Bu yapı taşlarını birlikte kullanarak MongoDB'de belgeleri seçebilir, gerekli alanları gösterebilir, sonuçları sıralayabilir ve dönen kayıt sayısını kontrollü biçimde sınırlandırabilirsin.