MongoDB'yi Node.js'ten kullanmak için resmi driver'ı kur (npm install mongodb), new MongoClient(uri) ile bağlan, client.db('name') ile bir veritabanı ve db.collection('name') ile bir collection seç. Her işlem (insertOne, find, updateOne, deleteOne) bir promise döndürür, yani onu await edersin. Dökümanlar düz JavaScript nesneleri olarak girer ve çıkar.
Program [ 'Dune', 'Neuromancer', 'Hyperion' ] yazdırır. shop veritabanı ve books collection'ı daha önce yoktu: MongoDB onları ilk eklemede oluşturur, toArray() de find() cursor'ının gösterdiği her dökümanı yükler.
Filtre ve projection ile döküman bulmak
Filtre, istediğin dökümanları tarif eden bir nesnedir. Düz değerler birebir eşleşir; $gt, $lt, $in ve $regex gibi operatörler iç içe bir nesneye yazılır. İkinci argümandaki projection hangi alanların geri geleceğini seçer.
recent, 1960'tan sonraki en yeni iki kitabı, önce Hyperion sonra Neuromancer'ı, yalnızca title ve year ile tutar; findOne ilk eşleşmeyi (ya da null) döndürür, countDocuments ise 10 ya da daha pahalı 2 kitap sayar. $gt: 1960'ı $gt: 1985 yaparsan yalnızca Hyperion kalır.
Güncelleme ve silme
updateOne(filter, update) eşleşen ilk dökümanı değiştirir. Güncelleme operatör kullanır: $set alanları değiştirir, $inc bir sayıya ekler, $unset bir alanı kaldırır ve $push bir diziye eleman ekler. updateMany ve deleteMany her eşleşme üzerinde çalışır.
Güncelleme bir dökümanla eşleşti ve onu değiştirdi, yani Dune artık 10 tutuyor ve stokta 2 tane var; stoğu olmayan kitabı silmek de geriye 1 bırakıyor. Bir güncelleme operatör kullanmak zorundadır: $set olmadan { price: 10 } geçirirsen driver onu reddeder (bütün bir dökümanı değiştiren çağrı replaceOne'dır).
ObjectId ve index'ler
Her döküman bir _id alır; sen ayarlamazsan driver bir ObjectId oluşturur. String olarak gelen bir id ile (örneğin bir URL'den) bir döküman bulmak için onu new ObjectId(id) ile sar. Bir index bir alanda aramayı hızlandırır, unique bir index de MongoDB'nin tekrarları reddetmesini sağlar.
Bir ObjectId string olarak 24 hex karakterdir ve düz string ile arama hiçbir şey bulmaz, bu yüzden o satır null yazdırır. İkinci ekleme unique index'i ihlal eder ve 11000 koduyla başarısız olur; "bu e-posta zaten kullanılıyor" durumunu böyle tespit edersin.
MongoDB'yi bir Express API'de kullanmak
Sunucu başlarken bir kez bağlan ve collection'ı paylaş; her istek için yeni bağlantı açma. Driver bir bağlantı havuzu tutar ve bağlantıları yeniden kullanır.
GET /books, her biri bir _id taşıyan iki kitabı da döndürür. Tek bir kitabı almak için bir id'yi GET /books/<id> içine kopyala ya da {"title": "Foundation", "year": 1951} gibi bir JSON body ile POST /books gönder ve kitapları yeniden listele.
Gerçek bir uygulama connection string'i koda yazmak yerine process.env.MONGODB_URI'den okur.
Driver'ın üstünde schema ve doğrulama istiyorsan Mongoose (npm install mongoose) onu sarar:
const Book = mongoose.model('Book', new mongoose.Schema({ title: String, year: Number }));
await Book.create({ title: 'Dune', year: 1965 });
Sık yapılan hatalar
toArray()'i unutmak. find() döküman değil, bir cursor döndürür. Onu loglamak bir cursor nesnesi gösterir; toArray() çağır ya da for await ile üzerinde dön.
Her istekte bağlanmak. Her new MongoClient kendi havuzunu açar. Başlangıçta tek bir client oluştur ve her yerde onu kullan.
Bir script'te client'ı hiç kapatmamak. Açık bir client, kodun bittikten sonra da süreci canlı tutar. Script'lerin sonunda await client.close() çağır; bir sunucu ise onu tüm ömrü boyunca açık tutar.
Sıkça Sorulan Sorular
mongodb driver'ı mı kullanmalıyım, Mongoose mu?
Driver resmi ve daha ince katmandır: düz nesnelerle ve MongoDB'nin kendi sorgu diliyle çalışırsın. Mongoose bunun üstüne schema, doğrulama ve model ekler; her dökümanın kontrol edilmesini istediğinde işe yarar. İkisi de aynı veritabanıyla konuşur ve Mongoose altta driver'ı kullanır.
Önce bir veritabanı ya da collection oluşturmam gerekiyor mu?
Hayır. MongoDB ikisini de onlara ilk döküman eklendiğinde oluşturur. client.db('shop') ve db.collection('books') yalnızca birer handle döndürür.
Connection string'i nereye koymalıyım?
MONGODB_URI gibi bir ortam değişkenine; onu process.env.MONGODB_URI ile oku. Barındırılan bir veritabanının string'i parola içerir, bu yüzden asla repository'ye commit edilmemeli.
id ile arama yaptığımda find neden hiç döküman döndürmüyor?
_id bir string olarak değil, ObjectId olarak saklanır, bu yüzden { _id: '65f1...' } hiçbir şeyle eşleşmez. Önce çevir: { _id: new ObjectId(id) }.