Agregasyon çerçevesi, verileri işlemeye, dönüştürmeye ve hesaplanmış sonuçlar döndürmeye olanak tanır. SQL’deki GROUP BY, HAVING, JOIN gibi işlemlere benzer kabiliyetler sunar.
Agregasyon işlemlerini (sıralama, filtreleme, gruplama, birleştirme) bir dizi işlem adımı (stage) ile gerçekleştirir.
| Operatör | Açıklama |
| — | — |
| $match
| Belirli koşullara uyan belgeleri filtreler. |
| $project
| Belirli alanları getirir veya yeni alanlar oluşturur. |
| $group
| Belirli bir alanı gruplar ve toplama işlemleri yapar. |
| $sort
| Belge sıralamasını değiştirir. |
| $limit
| Belge sayısını sınırlar. |
| $skip
| Belge sayısını atlar. |
| $unwind
| Dizi alanlarını ayrıştırır. |
db.kullanicilar.aggregate([
{ $match: { yas: { $gte: 25 } } },
{ $group: { _id: "$il", toplam: { $sum: 1 } } },
{ $sort: { toplam: -1 } }
])
Limit ve Skip işlemleri ile sorgu sonuçlarını sınırlayabilir ve atlayabiliriz.
db.kullanicilar.aggregate([
{ $project: { isim: 1, email: 1, _id: 0 } },
{ $limit: 2 },
{ $skip: 1 }
])
$lookup
operatörü, iki koleksiyon arasında birleştirme işlemi yapar, SQL’deki LEFT OUTER JOIN işlemine benzer.
db.kullanicilar.aggregate([
{
$lookup: {
from: "gonderiler",
localField: "kullanici_id",
foreignField: "kullanici_id",
as: "gonderiler"
}
},
{ $unwind: "$gonderiler" },
{ $project: { isim: 1, email: 1, "$gonderilen.text": 1 } }
])
Uyarı: NoSQL veritabanlarında JOIN işlemleri, SQL veritabanlarına göre daha karmaşıktır ve performans sorunlarına yol açabilir. Bu nedenle, JOIN işlemlerini dikkatli bir şekilde kullanmalısınız. ve gerektiğinde veri modelinizi yeniden dönüştürmelisiniz.
Aggregation Framework kullanırken performansı artırmak için şu ipuçlarını uygulayabilirsiniz:
$project
işlemlerinde sadece gerekli alanları getirin.$match
işlemlerini mümkün olduğunca erken aşamalarda$project
işlemleri ile gereksiz alanları çıkarın.$lookup
işlemlerini gerektiğinde kullanın ve gereksiz birleştirme
işlemlerinden kesinlikle kaçının.Indexler, veritabanı sorgularının hızını artırmak için kullanılır. Indexler, belirli alanlara hızlı erişim sağlar ve sorguların daha hızlı çalışmasını sağlar. Ancak, yanlış index kullanımı performans sorunlarına yol açabilir.
Basit sorgular için tek alanlı index oluşturulabilir.
db.kullanicilar.createIndex({ email: 1 }, { unique: true })
Birden fazla alan üzerinde index oluşturur.
db.kullanicilar.createIndex({ project_id: 1, kullanici_id: -1 })
Metin arama sorguları için text index oluşturulabilir.
db.kullanicilar.createIndex({ isim: "text" })
Coğrafi sorgular için geospatial index oluşturulabilir.
db.kullanicilar.createIndex({ konum: "2dsphere" })
Seyrek ve Kısmı index, daha verimli index oluşturmak için kullanılır.
db.kullanicilar.createIndex({ email: 1 }, { sparse: true }) // Seyrek Index
Yukarıdaki örnekte, email alanı null veya eksik olan belgeler indexlenmez.
db.kullanicilar.createIndex({ yas: 1 }, { partialFilterExpression: { yas: { $exists: true } } }) // Kısmi Index
Yukarıdaki örnekte, yas alanı olan belgeler üzerinde index oluşturulur.
Kullanım amacı ne olabilir:
NoSQL veritabanları geliştirilme felsefesine göre normal şartlarda ACID özelliklerini desteklemez. Ancak, bazı NoSQL veritabanları (örneğin, MongoDB) belirli durumlarda transaction benzeri işlemleri desteleyebilir.
Büyük veri setlerini yönetmek için sharding ve replikasyon teknikleri kullanılır. Sharding, veriyi parçalara bölerek farklı sunuculara dağıtır ve yükü dengeler. Replikasyon, veriyi yedekleyerek yüksek erişilebilirlik sağlar.
Sharding, veriyi parçalara bölerek farklı sunuculara dağıtır ve yükü dengeler. Shard anahtarına göre veri parçaları oluşturulur ve farklı sunuculara dağıtılır. Bu kısımda anahtar seçimi kritik öneme sahiptir.
Neden: Eğer yanlış bir anahtar seçilirse, veri dağılımı dengesiz olabilir ve bazı shard’lar diğerlerinden daha fazla yük alabilir. Bu durumda, performans sorunları ve hatalar ortaya çıkabilir.
sh.enableSharding("sosyalmedya")
sh.shardCllection("sosyalmedya.gonderiler", { kullanici_id: 1 })
Soru: Sosyal Medya uygulamasında postları country alanına göre sharding yapmak istesek bu mantıklı olur mu? Nasıl bir yaklaşım izlemeliyiz? Cevap: Sosyal medya uygulamasında post’ları ülke (country) alanına göre sharding yapmak ilk bakışta mantıklı gibi görünse de, pratikte bazı problemler doğurabilir. Sharding’in temel amacı, veriyi yatay olarak ölçekleyerek yükü dengeli bir şekilde farklı shard’lara dağıtmaktır. Bu nedenle seçeceğiniz shard key’in veri dağılımında dengesizlik yaratmaması ve sorgu örüntülerinize uygun olması çok önemlidir. Nedenleri:
Daha Mantıklı Yaklaşım ne olabilir:
{ country: 1, createdAt: 1 }
gibi bir kombinasyon kullanıldığında, sadece ülkelerin değil aynı zamanda zamansal dağılımın da hesaba katılması sağlanır. Ancak burada da country alanının düşük kardinalite sorunu giderilemezse, ek bir alanla dengelemek gerekebilir.{ _id: "hashed" }
şeklinde bir shard key kullanarak, veriyi rastgele dağıtabilirsiniz.Amacımız datayı bölmekten çok bölgesel olarak dağıtmak ise zone sharding
kullanılabilir. Bu durumda veriyi coğrafi olarak bölmek yerine, veriyi farklı bölgelere da
Replication, veriyi yedekleyerek yüksek erişilebilirlik sağlar. Veritabanı sunucuları arasında veri kopyalama işlemi gerçekleştirir ve veri kaybını önler. Primary-Secondary replikasyon modeli yaygın olarak kullanılır.
mongod --port 27017 --dbpath /data/db1 --replSet rs0 // ile primary sunucu oluşturulur
mongod --port 27018 --dbpath /data/db2 --replSet rs0 // ile secondary sunucu oluşturulur
mongod --port 27019 --dbpath /data/db3 --replSet rs0 // ile secondary sunucu oluşturulur
rs.initiate({
_id: "rs0",
members: [
{ _id: 0, host: "localhost:27017" },
{ _id: 1, host: "localhost:27018" },
{ _id: 2, host: "localhost:27019" }
]
})
Sharding ve replikasyon, büyük veri setlerini yönetmek ve yüksek erişilebilirlik sağlamak için kullanılır. Aşağıda
Sharding Kullanım Senaryoları:
Replikasyon Kullanım Senaryoları:
NoSQL veritabanlarında da güvenlik, kimlik doğrulama, yetkilendirme ve şifreleme önemli konulardan biridir.
Kullanıcı oluşturma ve rol bazlı yetkilendirme işlemleri yapılabilir.
db.createUser({
user: "uygulamaHesaabi",
pwd: "sifre123",
roles: [{ role: "readWrite", db: "sosyalmedya" }]
})
Yetkilendirme işlemleri ile kullanıcıların belirli veritabanları ve koleksiyonlara erişimini kontrol edebilirsiniz.
db.grantRolesToUser("uygulamaHesabi", [{ role: "readWrite", db: "sosyalmedya" }])