MongoDB
Json / doküman bazlı çalışan, SQL desteklemeyen NoSQL denen tabanlardan en ünlüsü şu anda MongoDB. Mongo birleştirme (join) komutunu desteklemez, dokümanlara tekil olarak erişmeyi ya da sorgulamayı destekler, Json formatında objeleri tabana alıp verebilir. Sorgulama şöyledir - eğer dokümanın Json'ı içinde hazı öğeler set edilmiş, diğerleri edilmemiş ise, edilmiş olan ögeler üzerinden bir filtre yaratılabiliyor. Büyüktür, küçüktür filtre durumları içinde yine Json üzerinden bir sorgulama formatı var.
Mongo ile "sema değiştirmek" için ALTER TABLE
gibi bir komuta gerek
yoktur; yeni bir öğe (kolon) gerekirse, o öğe dokümana eklenir, ve
tabana yazılır. Yani felsefe olarak ilişkisel tabanlardan çok farklı
bir yaklaşımı var. Bu felsefede sema önceden tanımlanan bir şey
değildir. Bunun sayesinde "sema değişimi" sonrası eski verinin
yapısının değiştirilmesine gerek yoktur. Tabii bu özellik uygulama
yazılımcılarına bazı ek sorumluluklar yükleyebilir; belki dökümanları
versiyonlamak gerekecektir vs.
Ölçekleme açısından Mongo'nun ilginç bazı özellikleri var. RDBMS durumunda bilinebileceği gibi ölçeklemenin standart yollarından biri master/slave (usta/çırak -bu tercüme daha iyi-) sistemi. Usta/çırak ortamında ekleme, güncelleme tek bir makina olan ustaya gider, yeni veri arka planda çıraklara dağıtılır, okuma çıraklardan yapılır. Usta tek makinadır, çıraklar pek çoktur, "çoğunlukla okuyan (read-mostly)" uygulamalarda bu sistem iyi işler (mesela YouTube gibi bir uygulama, insanlar çoğunlukla video seyrederler, daha az yüklerler).
Bu sistemin zayıf noktası ustanın çökme durumunda sistemin çökmekten kurtulmasının zorluğu. MongoDB'de kopya kümeleri (replica set) kavramı vardır; Yazım sırasında usta Mongo kümesi içinde oy verilerek seçilir (tabii ki ustanın içeriği çıraklara dağılıtır), ve eğer usta çökerse oy birliği ile başka bir çırak hemen usta haline getirilir. Bu özellik MD'nin paketten çıktığı haliyle sahip olduğu bir özelliktir.
Kurmak
sudo apt-get install mongodb-org
Başlatmak, durdurmak
sudo systemctl start mongod
sudo systemctl stop mongod
Eğer belli bir dizin altına taban dosyaları yazılacak şekilde başlatmak istersek,
mongod --dbpath /tmp/mdb
gibi bir komut olabilir. Taban dosyaları /tmp/mdb
altına gidecektir.
Python ile erişim için
sudo pip install pymongo
Bir doküman yazan örnek kod
import sys
from datetime import datetime
from pymongo import MongoClient
from pymongo.errors import ConnectionFailure
def main():
try:
c = MongoClient(host="localhost", port=27017)
except ConnectionFailure, e:
sys.stderr.write("Could not connect to MongoDB: %s" % e)
sys.exit(1)
dbh = c["test_db"]
assert dbh.connection == c
user_doc = {
"username" : "janedoe",
"firstname" : "Jane",
"surname" : "Doe",
"dateofbirth" : datetime(1974, 4, 12),
"email" : "janedoe74@example.com",
"score" : 0
}
dbh.users.insert(user_doc, safe=True)
print "Successfully inserted document: %s" % user_doc
print 'id is', user_doc['_id']
if __name__ == "__main__":
main()
Önemli bir noktaya dikkat: üstte yazım öncesi taban filan yaratmadık, peki yazım nasıl işledi? Eğer yazım sırasında hedef taban ortada yoksa MD onu otomatik olarak yaratır! Bu yaklaşım da RDBMS durumundan oldukca farklı.
MD tabana asenkron yazımı destekler - eğer üstte safe=True
seçeneği
verilmezse, yazımın sonucu beklenmez, çağrı hemen geri döner. Bu tür
bir yazım ne zaman gerekli olur? Belki MD loglama için kullanılıyor,
bu durumda hızlı şekilde bilgiyi yazmak önemli, pek çok diğer kullanım
da olabilir.
Ayrıca MD insert
sırasında mesela w=2 gibi bir seçenek ile, "kopya
kümesi içinde kesinlikle iki makinaya yazım yapılmasını istiyorum"
gibi bir şart getirebilir. Bu makinalardan biri usta olacak herhalde,
diğeri de onun kopyasını içeren çıraklardan biri.
Diğer pek çok özellik var. İyi bir referans kaynağı N. O'Higgins'in MongoDB & Python kitabı.
GUI
"Acaba vs vs veri tabana yazılmış mı?" gibi incelemeler için MD komut satırından sorgulama yerine, Robomongo iyi bir araç
Linux için olan versiyonu indirdik, sudo dpkg -i
ile
kurulur. Bağlanmak için makina localhost, port olağan port 27017, ve
olağan (default) taban ise incelenecek taban ismi our. Bağlantı
kaydedilir ve connect üzerinden tıklanarak taban incelenmeye
başlanır. Araç Squirrel, Toad gibi bir araç.
Örnekler
Mongo listeler (collections) üzerinden çalışır. Bir obje yarattığımızda onu direk yaratmayız, bu objelerin olduğu bir listeye yeni bir objeyi ekleriz.
Üstte kimlik üretilmesini gördük, kimliği kendimiz de tanımlayabilirdik,
from pymongo import MongoClient
connection = MongoClient()
stocks = connection['db1'].stocks
sym = "APL"; dt = 20100101; open=11; low=10; price=12
new_row = {"_id": {"sym": sym, "dt": dt },"o": open,"l": low,"p": price}
stocks.save(new_row)
stocks.save(new_row)
Out[1]: {'dt': 20100101, 'sym': 'APL'}
stocks.count()
Out[1]: 1
_id
'yi kendimiz verdik. Böyle olunca ardı ardına yapılan aynı
kimlikli .save
tek bir obje yarattı. İkinci çağrı birinci üzerine
yazdı.
Sorgulama, Sınırlama
Sıralama ve sonuçları sınırlama örneği. Bazı ek satırlar ekleyelim,
sym = "APL"; dt = 20100101; open=11; low=10; price=12
new_row = {"_id": {"sym": sym, "dt": dt },"o": open,"l": low,"p": price}
stocks.save(new_row)
sym = "APL"; dt = 20100102; open=11; low=10; price=12
new_row = {"_id": {"sym": sym, "dt": dt },"o": open,"l": low,"p": price}
stocks.save(new_row)
sym = "APL"; dt = 20100103; open=11; low=10; price=12
new_row = {"_id": {"sym": sym, "dt": dt },"o": open,"l": low,"p": price}
stocks.save(new_row)
stocks.count()
Out[1]: 3
Altta tarihle büyükten küçüğe gidilecek şekilde sıralama yaptık (-1
ile) ve limit(1)
ile alınan sonuçları bir tane ile sınırladık, bu
tabii ki bize en tepedeki sonucu vermiş oldu ki bu tarihlerin en
büyüğüne ait satır idi.
q = { "$query" : {"_id.sym": sym}, "$orderby":{"_id.dt" : -1} }
res = stocks.find(q).limit(1)
res = list(res)
print (res)
[{'l': 10, 'o': 11, '_id': {'sym': 'APL', 'dt': 20100103}, 'p': 12}]
Sorgularda büyüktür, küçüktür kullanımı için belli bir tarihe eşit ve ondan büyük olan satırları alalım,
q = { "$query" : {"_id.dt": {"$gte": 20100102 }} }
for x in list(stocks.find(q)): print (x)
{'l': 10, 'o': 11, '_id': {'sym': 'APL', 'dt': 20100102}, 'p': 12}
{'l': 10, 'o': 11, '_id': {'sym': 'APL', 'dt': 20100103}, 'p': 12}
Silmek
Eğer bir sorgu kriterine uyan objeleri silmek istersek,
stocks.remove( {"_id.dt": {"$gte": 20100102 } } )
stocks.count()
Out[1]: 1
Tum dokumanlari silmek icin
stocks.remove( { } )
stocks.count()
Out[1]: 0
Kaynaklar
Yukarı