MongoDB ile Flörtleşme ve MongoLab ile Bulut Veritabanı

NoSQL vertiabanı motorları son yıllarda çok popülerleşti, çünkü yapısız olmalarından dolayı daha kolay mimari değişiklik yapabileceğiniz veri yapıları olduğu için tercih edilmeye başladı. Ölçeklenebilirlik de klasik sql veritabanlarının sınırlı ve geleneksel kaldığı konulardı.
NoSQL çıkışı kesinlikle modern bir çözüm olarak görülebilir.

İnternette bir çok karşılaştırma, performans analiz yazıları bulabilirsiniz sql ve nosql veritabanları hakkında. Ancak her yere uyan mükemmel bir çözüm yok. Benim gördüğüm kadarıyla, hibrid ve akıllıca kurgulanarak dengelenmiş ve dağıtılmış sistemler en yaygın kullanımlar. Yani bazı şeyleri nosql ile daha zor ve daha çok kodlama zamanı harcayarak yapabilir, bazı şeyleri de sql ile yönetemez ve yapamazsınız.

Daha teknik konulara giriyorsanız zaten bu yazıdan daha çoğuna ihtiyacınız var 🙂 Bu yazı daha çok mongo’ya giriş ve flörtleşme dönemi hakkında.

Eğer MongoDB’yi denemek istiyorsanız, mongodb sunucusunu bilgisayarınıza yüklemek zorunda değilsiniz. Kurulumu da çok zor değil fakat sadece denemek için sunucu kurulumu konfigurasyonu gibi şeylerle uğraşmak zorunda değilsiniz. Sadece istemci sürücülerini kurmanız yeterli. Bu konu hakkında mongodb dökümantasyonundaki http://docs.mongodb.org/ecosystem/drivers/php/ sayfasını inceleyebilirsiniz.

MongoLab adında bağımsız bir servis sayesinde ücretsiz bir mongo veritabanı oluşturabilir ve denemelerinizi onun üstünde yapabilirsiniz. MongoLab veritabanı ve kullanıcınızı oluşturduktan sonra açık erişim izni veriyor. Dolayısıyla php’den veya herhangi diğer bir ortamdan doğrudan erişebiliyorsunuz.

Tabi ki servisin amacı mongo denemek isteyen insanlara servis sunmak değil. MongoLab bulut veritabanı servisi. Veri dosyalarının saklanmasını istediğiniz alt servisi (Amazon, Rackspace, Windows Azure vs…), hatta yüzeysel de olsa bölge seçebiliyorsunuz (Amerika veya Avrupa veya uzak doğudaki bir veri merkezi şeklinde).

MongoLab 500mblık bir alanı ücretsiz sağlıyor. Diğer sınırlamalarını bilmiyorum fakat ufak projeleriniz için veya deneme yapmak için ideal. Eğer uygulamanız çok veri kullanmaya başlarsa küçük, büyük paketleri veya kurumsal hizmetlerinden faydalanabilirsiniz.

MongoLab ile tamamen php mongo eklentisi bağımlılığından da kurtularak doğrudan servisin basit REST apisini kullanabilir ve tek başına çalışan bir uygulama yazmanız da mümkün.

Konumuz mongo iken, birkaç php-mongo interaksiyonunu denediğim bir php dosyasının kodunu doğrudan vermek istiyorum.

İlk satırlarda göreceğiniz dsn’i mongolab’den edineceğiniz sunucu adresi ve portunu (tahminimce her kullanıcı için farklı olma durumu var), veritabanı kullanıcı adınız ve şifrenizi belirterek tek parça string şeklinde belirttiginiz takdirde bağlantı sağlayabileceksiniz.

Mongo, küçük uygulamalarda veri düzeni zorunluluğu olmadığı için kullanması çok keyifli, fakat verinizi dökümante etmeyi unutmayın. Yoksa neyin ne olduğunu unutur veya ipin ucunu kaçırarak karmaşık bir veri yığını elde edebilirsiniz günün sonunda.

MongoDB dökümantasyonunu inceleyerek indeksleme, sorgulama ve veri yönetimi nasıl yapılıyor fikir edinebilirsiniz. Ayrıca php manual’daki bazı SQL örneklerinin php ile mongo sınıfında nasıl yapıldığını gösteren bu sayfayı: http://php.net/manual/en/mongo.sqltomongo.php incelemekte fayda var.

MongoLab servisinin adresi https://mongolab.com

PHP ile tekil anahtar oluşturmak

Türkçesini çok bulamadığım hash kelimesini anahtar olarak kullanacağım. Burada aslında bahsettiğim anahtar herhangi bir veri grubunuza atadığınız, sayısal olmayan kimliklerden bahsediyorum. Yani rasgele üretilmiş belirli bir uzunlukta olan kimlikleri her yerde kullanıyoruz.

Neden sayısal bir kimlik kullanmak yerine bu anahtarlara ihtiyaç duyacağınızı en açık şekilde şöyle anlatabilirim. Mesela tahmin ederek erişilmesini istemeyeceğiniz ama şifre veya kullanıcı girişi gibi herhangi bir sınırlama koyamayacağınız bir sayfanız var, örnek veriyorum yapılacak işler listesi veritabanı oluşturuyorsunuz ve her kayıt bir yapılacak iş listesi. Veritabanında sayısal bir kimliğe yani numaraya sahip bu kayıtlar. Hazırladığınız bir php sayfası da liste numarasına göre yapılacak iş listesinin detayını ekrana döküyor.

Eğer liste_detay.php?no=145 gibi basit bir şekilde tutarsanız url’i oynayarak başkalarının listelerine erişebilir, sadece erişmek değil sistemdeki tüm listeleri basit bir script ile tahmin edebilir veya tarayıp kaydedebiliriz. Böyle bir durumda listelerinizi sadece sayısal değil, tahmin edilemeyecek bir anahtar ile (örneğin: t34de6gx) tanımlamak istiyorsunuz.

Bu noktada rastgele bir anahtar üretebilirsiniz, bunu yapmak çok zor değil. PHP’deki rasgele sayı üretme fonksiyonunu kullanarak ve bir karakter dizisinden rastgele elemanlar çekerek bir kelime üretebilirsiniz.

Bunu daha pratik bir şekilde tek satırda bile yapabilirsiniz:

Bu satır size 6 karakterlik bir kelime üretecektir. Basitçe str_shuffle fonksiyonu ile özel karakter içermeyen ve rakamlarında dahil olduğu bir alfabeyi karıştırıyor ve başındaki ilk 6 karakteri alıyoruz.

Şimdi bu, işin basit kısmı. Eğer veritabanındaki bir veri set için bu anahtarı oluşturuyorsanız üretilen anahtarın veri setinde daha önce kullanılıp kullanılmadığını test etmek zorundasınız. Sonuçta tekil bir anahtar oluşturuyorsunuz. Bu arada veri setiniz mysql veya bir sql veritabanında olmak zorunda değil, bir xml, csv veya txt dosyasında saklı olan bir set için de benzer şeyi uygulayabilirsiniz.

Veritabanındaki veriyi test ederek bir anahtar oluşturmanın en kısa ve basit kodu şöyle:

Bu kod, veritabanında olmayan bir anahtar üretmenizi sağlayacaktır. Sonra verinizi hazırlayıp tablonuza yeni kayıdınızı ekleyebilirsiniz.

Pear’da MDB2 ile veritabanı işlemleri

MDB2 nedir?

MDB2 pear’da eskiden DB adıyla geliştirilen ve bir süre önce gelişimi durdurulup projeyi mdb2 olarak devam ettirdikleri bir veritabanı yönetim kütüphanesidir. Aslında sırayla girdiğimiz mysql_connect, mysql_select_db, mysql_query … gibi işlemleri biraz daha ortak yapıda kullanmamızı sağlayan, çeşitli yetenekleri olan güvenli bir kütüphane.

Normalde veritabanımıza (mysql, mssql veya pgsql farketmez) bağlanırken bağlantı kaynak değşkeni oluştururuz. Örneğin :

sonra da bu değişkeni kullanarak fonksiyonlarımızı işletiriz. Bu noktadan sonra veritabanı seçeriz ve sorgular üretip sonuçlarını işleriz.

MDB2’de veritabanı bağlantı cümleleri vardır. Tek hamlede hem bağlantı değişkenimizi oluşturur hem de veritabanı seçeriz.

connect yerine factory fonksiyonunu da kullanabilirsiniz, aynı işi görmektedir. Bağlantı cümlesi, pear dizininde MDB2’nin dizinindeki Drivers klasöründe yüklediğiniz veritabanı sürücülerine göre değişir.

Genellikle mysql için kullanacağınızdan örnek vermek gerekirse

yeterince açık ama yine de üstünden geçeyim. Gördüğünüz gibi cümle bir protokol adresi gibi. Yani ftp’ye bağlanmaktan farksız 🙂 önce protokol türünü belirtiyoruz (mysql, pgsql, sqlite vs) arada “://” işaretlemesinden sonra kullanıcı, “:” ve şifreyi belirtiyoruz. @ işaretinden sonra sunucu adresi. Sonrasında da klasör ifade eder gibi veritabanı adını veriyoruz. SQLite için ise protokoldan sonra doğrudan dosya adresini veriyorsunuz. (Daha fazla bilgi için http://pear.php.net/manual/en/package.database.mdb2.intro-dsn.php)

Biliyorsunuz mysql mssql sqlite pgsql arasında çok fazla kural farkı yok. Yani aynı sorgularla veri ekleyebiliyor, güncelleyebiliyor, silebiliyor ve listeletebiliyoruz. Böylece aynı veritabanı yapısına sahip mysql ile çalışan bir projeyi mssql’e geçirmek çok da zor olmuyor 🙂

Şimdi basitçe bir sorgu işletmeyi göstereyim. MySQL’de bir sorgu işletmek için:

şeklinde kullanıyorduk. MDB2’de de çok farklı değil:

sorgu sonucunu işlerken

şeklinde kullanırdık. İşte bu noktada MDB2 bize birçok kolaylık sağlıyor. MDB2’de sürü sepet sonuç işleme fonksiyonu var fakat biz 2 tanesini kullanacağız.

Bu kodda $uye_bilgisi değikeni dizi olarak indisleri normal numara olmak üzere
$uye_bilgisi[0]’da no,
$uye_bilgisi[1]’da adi,
$uye_bilgisi[2]’da eposta,
alanlarını tutar. fetchRow fonksiyonunun parametresiyle “İşleme Türü”nü ayarlarız. Eğer ayarlamazsak, veri az önceki gibi gelecektir.

olarak kullanırsak taboldaki indis adlarına göre doğrudan seçebiliriz verimizi ($uye_bilgisi[no], $uye_bilgisi[adi] $uye_bilgisi[epsta]). Bunu her seferinde yapmak yerine, veritabanı bağlantısı yaptıktan hemen sonra

ile “İşleme Türü”nü tüm betik için ayarlamış oluruz. Bundan sonra ilk verdiğim örnek koda göre işleminizi kolayca yapabilirsiniz.

Genellikle 2 tür veri çekeriz, tek satırlık sonuçlar veya listeler. Mesela yukarıdaki sql cümlesi bize tek kayıt döner yani 5 nolu üyenin bilgilerini. Bunun için doğrudan fetchRow() kullanarak bilgileri aldık. Çok satırlı bir sql sorgusu işletiyor olsaydık :

şeklinde fetchRow()’u while içinde değişkene atama olayı olarak tanımlayacaktık. Böylece kayıtlar bittiğinde atama gerçekleşmeyecek ve döngü duracaktı. Fakat bu noktada kolaylık olsun diye tüm kayıtları çok boyutlu diziye doğrudan almak için fetchAll() fonksiyonunu kullanıyoruz.

Tabi $tum_uyeler dizisi bizim listeledigimiz sql sonucunu dizi olarak donuyor bize. Dizi boyutu da kayıt sayısı yani üye sayısını veriyor count($tum_uyeler) ile. Aynı işlemi $sorgu->numRows() ile de yapabilirdik. Zira while ile kullanıyorsak dizi boyutu diye birşey olmayacak ve numRows‘u kullanacağız.

Bu iki yol da neredeyse aynı. while, foreach veya verinizin dizi olarak olup olmaması alışkanlıklarınız ve programlama anlayışınız ile ilgili birşey.

Daha da hızlı dizi olarak almak istiyorsanız

size tüm üyleri çok boyutlu dizi olarak $uyeler değişkenine atayacaktır. query + fetchAll işleminin kısaltılmışıdır 🙂

Ek olarak

$sorgu->numCols() ile sorgudan kaç tane kolon çıktığını öğrenebilirsiniz.
Aynı zamanda $sorgu->fethcCol() ile verinizi kolon kolon alabilirsiniz de (nerede kullanacağınızı bilmiyorum ama işe yarayabilir).

$sorgu->getColumnNames() ile işlenen kolonları dizi olarak alırsınız. İşleme sırasıyla yerleşecektir dizide. Sorgudan hangi kolonların döndüğünü bilmediğiniz sorgularda kolonları meta olarak basabilmek için kullanabilirsiniz bu fonksiyonu.

$sorgu->seek(5) ile sorguları dönerken 5 kayıt atlamanızı sağlar (ilginç).

$db->lastInsertID() ile son “insert into uyeler (…) values (…)” tipi, veri kayıt sql sorgunuzda eklenen kayıt için, auto_increment olan kolona atanan numarasını döner.

Hata yakalamak

Sorgunuzu çalıştırırken birçok nedenden dolayı çalışmayabilir.

kullanımı; PEAR:isError($sorgu) $sorgu degişkeni ile tanımlanan veritabanı sorgu nesnesinde hata varsa, aynı nesnedeki getMessage() fonksiyonu ile hata mesajını iletir.

http://pear.php.net/manual/en/package.database.mdb2.php adresinden mdb2 manual’ına ulaşabilirsiniz.