C# / MongoDb – MapReduce

Herkese merhaba. Bugün yazacağım makalede MongoDb ile MapReduce işlemleri yapacağız. Öncelikle MapReduce yapısı hakkında kısaca bir giriş bölümü yazacağım.

MapReduce dağıtık mimari üzerinde büyük verilerin kısa zamanda analiz edilebilmesini sağlayan bir sistemdir. Verileri analiz edip onlardan aggregate sonuçlar üretmek için kullanılır. Map fonksiyonu ile belirtilen key/value değerlerine göre veriler toplanır. Ardından Reduce fonksiyonu ile toplanan veriler aggregate sonuçlara çevrilir.

  • Map fonksiyonunu SQL select sorgusu olarak düşünebiliriz.
  • Reduce fonksiyonunu ise; count, having, avg gibi SQL sorguları olarak düşünebiliriz.

Hesaplama map fonksiyonu içerisinde key/value değerleri alır ve reduce işlemi sonrasında key/value değerlerine göre bir çıktı üretir. Her iki fonksiyonda kullanıcı tarafından yazılmaktadır.

Aşağıda gösterilen örnekte her kelimeden kaç adet bulunduğu hesaplanıyor. Öncelikle değerler 3 gruba ayrılıyor. Ardından mapping kısmında her grupta bulunan kelimeler sayılıyor. Sonrasında her grupta aynı olan kelimeler bir bölümde toplanıyor. Reduce aşamasına geçildiği zaman ise her bölümde toplanan kelimeler sayılıyor ve en son değerimiz ekrana çıkarılıyor. Giriş değerimizin büyük boyutta olduğunu düşünelim. Böylece istenilen sorgu map reduce ile kolayca elde edilmektedir. Map reduce ile ilgiyi geniş bilgi internette fazlasıyla mevcuttur. Detaylı bilgi için; research.google, wikipedia

map-reduce-flow

Örnek: Bu yazıda göstereceğim map reduce işlemi daha önce üzerinde örnekler yaptığım restaurants collection üzerinde olacaktır. Collectionda bulunan her documentta restaurantın bulunduğu semt adı bulunmaktadır. Map fonksiyonu ile semt değerine göre gruplama yapılacak. Ardından Reduce fonksiyonu ile her semt değeri için mevcut olan restaurant değerleri toplanıp çıkış değeri olacak gösterilecektir. Ekstra olarak restaurantları yemek türüne göre filtreleyip hangi yemek tipinden nerede kaç restaurant var görebiliriz.

  • Veritabanı için gerekli bağlantılar

1

  • MapReduce işlemleri için gerekli javascript fonksiyonlarını yazalım. MongoDb’de MapReduce işlemini uygulamak için fonksiyonlar javascript formatında yazılmalıdır. Map fonksiyonu ile borough (ilçe) değeri anahtar olarak belirtilmiştir. Value değeri olarak 1 yani her value değeri için o değer üzerine +1 eklenecektir. Reduce fonksiyonu ile values dizisine biriken değerler her key değeri için toplanıyor. Finalize fonksiyonu içerisinde toplanan değerler integer olarak ekrana döndürülüyor. Finalize fonksiyonu reduce işleminden sonra yapılacak olan düzenlemelerin uygulandığı fonksiyondur.

 

2

  • Restaurant tipine göre filtreleme yapmak istersek;

3

  • Öncelikle MapReduceOptions ile gerekli ayarları yapıyoruz. Giriş değeri restaurant sınıfı, çıkış değeri ise BsonDocument olarak belirtilmiştir. MapReduce metodunda tanımlarını yaptığımız fonksiyonlar (map-reduce) ile options parametresine belirttiğimiz ayar değerlerini yazıyoruz. Ardından tüm sonuçları await results.ToListAsync() ile docs değişkenine atıyoruz. Bütün bu işlemleri yaptığımız metod async değer döndürmelidir. Çünkü MongoDb yeni sürümü ile async/await olarak sorguları çekmekteyiz. Foreach kısmında ekrana yazma işlemleri yapılmaktadır.

4

  • Filtresiz ekran çıktısı. Sonuçta görüldüğü gibi 25.360 değer mevcuttur. MapReduce işlemi ile tüm verileri tarayıp az sürede sorgu gerçekleşmektedir.

restaurantoutput

  • Filtre kullanılarak yapılan sorgu sonucu oluşan ekran çıktısı. Restaurant yemek tipi “irish” olan restaurantları sorguluyor.

restaurantoutputfilter

Mevcut veriler için MapReduce işlemini gerçekleştirdik. Peki yeni veriler eklendiği zaman tekrar tüm veriler aynı işlemden geçirilmeli mi? Geçirilirse büyük veriler için maliyet kaybı olacaktır. Bu durumlar için Incremental MapReduce uygulanır. Sadece yeni eklenen verilere işlem uygulamak için, örneğin belli bir tarihten sonraki eklenen değerleri almak için bir sorgu yazarız. Böylece sadece yeni veriler MapReduce işlemine tabi olur. İşlem bitince eski sonuçlara yeni sonuçlar eklenir.

İngilizce versiyonu

Kaynaklar

MapReduce Doc

Advertisements

MongoDB – Sorgu Operatörleri

MongoDB ile ilgili yazmaya başladığım yazı serisinin 2.yazısıyla devam ediyorum. Giriş olarak yazdığım ilk yazının linki

2. yazıda ise shell üzerinden sorgulama için kullanılan operatörleri göstermeye devam edeceğim.

  • Insert ile kayıt işlemi;

doc = { “name”: “smith”, “age”:”30 }  db.test.insert(doc)

  • Karşılaştırma operatörlerine bakacak olursak: $eq(eşit), $gt(büyük), $gte(büyük eşit), $lt(küçük), $lte(küçük eşit), $in(içinde).

db.scores.find({score: {$gt:95}} : 95 < x

db.scores.find({score: {$gt:95, $lte:98}} : 95 < x <=98

  • $exists operatörü, belirtilen veri kısmının bulunduğu durumları listeler.

db.test.find({profession:{$exists:true}})

  • $regex operatörü

db.test.find({name:{$regex:”a”}}) : içinde a değeri olan isimler

$regex:”a$” : sonu a ile bitenler / $regex:”^a” : a harfi ile başlayan

db.users.find({name:{$regex:”a”}, email:{$exists:true}})

  • $or operatörü. Örn: İçinde ismi e ile bitenlere veya yaş değeri bulunanları;

db.users.find({$or:[{name:{$regex:”e$”}}, {age:{$exists.true}}});

db.scores.find({$or:[{score:{$lt:50}}, {score:{$gt:90}}]};

  • $and operatörü

db.users.find({$and:[{name:{$gt:”c”}}, {name:{#regex:”a”}}]});

  • Count ile sorgularda bulunan değer sayısını hesaplamak

db.scores.count({type:”essay”, score:{$gt:90}});

 Bundan sonra kullanacağım kodlarda mongodb sitesinden indirilip veritabanına eklenen restaurants collection verilerini kullanacağım.Yükleme ve kurulum için

 Aşağıda gösterilen resimde restaurants collection içinde bulunan herhangi bir veri gösterilmiştir.

mongo restaurant findone
findone ile rastgele veri çekmek
  • db.restaurants.find({ borough: “Brooklyn” }) brooklyn olan veriler getir.
  • db.restaurants.find({“grades.grade”:”A”}) grades dizisi içinde grade değeri A ise, sorgu sonucu o değerleri getir.
  • db.restaurants.find({“grades.score”:{$gt:10}}) score değeri 10’dan büyük olan verileri getir.
  • db.accounts.find({name:{$in:[“Ali”,”Ayşe”]}}) isim değerleri ali ve ayşe olan verileri getir.
  • db.scores.update({“score”:{$lt:70}},{$inc:{“score”:10},{multi:true}) eğer not değeri 70’den az ise, not değerine +10 eklenecektir. multi=true ile çoklu update işlemi aktif edilir.

Bu yazıda anlattığım sorgular için kullanılan sorgu operatörler bunlardır. Daha detaylı bilgi MongoDB sitesinde mevcuttur. Geniş bir dokümantasyon bulunmaktadır. Özelleştirilmiş sorgular çekmek için çeşitli parametreler kullanıyor. Diğer yazılarımda MongoDB ile ilgili özellikleri yazmaya devam edeceğim.

MongoDB – Giriş

Sıkça kullanılan NoSQL veritabanlarından biri olan MongoDB’yi anlatmak için başladığım yazı serisinin, ilk yazısında MongoDB kurulumu ve shell üzerinden yapılan işlemleri göstereceğim.

NoSQL kavramını anlattığım yazı

Kendi sitesinde geniş bir anlatım bulunmaktadır. İncelemek için link

MongoDB ilişkisel olmayan(NoSQL) veritabanıdır. Kısaca özelliklerine bakalım;

  • Verileri JSON document olarak tutmaktadır. MongoDB’de BSON olarak adlandırılmaktadır.
  • Doküman tabanlı bir NoSQL veritabanıdır.
  • Verileri JSON formatında tutarken herhangi bir format zorunluluğu yoktur.(Schemaless)
  • İlişkisel veritabanlarında bulunan join yapısı ve transactionlar kullanılmamaktadır.

{ a:3, b:7 } , { a:3, b:7, c:8 } ( Schemaless özelliği )

MongoDB kurulumu için; İndirme linki – Kurulum , Kurulum 

MongoShell ile işlemler

MongoShell ekranını kullanarak, MongoDB üzerinde işlemleri yaparız. Eğer C#,Java veya başka bir dil ile birlikte kullanmak istersek o diller için hazırlanmış mongodb driver indirilip uygulamaya bağlanmalıdır.

Windows kullanıyorsak cmd kullanarak, ilgili dizinde mongod komutu ile serverı çalıştırıyoruz. Ardından mongo.exe’yi çalıştırmak için mongo komutunu yazarak shell ekranı cmd üzerinde açılmaktadır.

Help komutu ile yapabileceklerimiz gösteriliyor.

1

Shell üzerinde yapacaklarımızı inceleyelim. Aşağıda doc adında bir json document yaratıyoruz ve bu doc değişkenini test veritabanımıza kaydediyoruz. Kayıt işlemi yaptığımız zaman MongoDB otomatik olarak _id değerini eklemektedir. Save ile kayıt yaparsak o id değeri ile kayıtlı değer varsa, değeri güncelleyecektir. Insert kullanırsak sadece kayıt yapacaktır. Eğer aynı id ile kayıt değer varsa hata verecektir. MongoDB ile her oluşturulan id değeri birbirinden bağımsız olup, aynı id ile kayıt işlemini shell üzerinden yaparsak farkı göreceğiz.

Daha sonrasında db.test.find() komutu ile veritabanında olan kayıtları getirecektir. .pretty() kullanarak düzenli gösterilmeyi sağlıyoruz. Eğer rastgele olarak tek bir kayıt getirmek istersek findOne() metodunu kullanırız.

mongo2

Veriyi güncellemek için aşağıda bulunan yapıyı kullanırız. Json documentlar içinde John adlı değer tutan kısımda yaş değerini 30 yapıyoruz. Bu işlemi gerçekte isim değeri yerine, id değeri ile yaparız. Çünkü birden fazla john isimli kullanıcı olabilir.

db.test.update({ “name”: “john” },{ $set :{ “age”:30 } })

Veriyi silmek için ise;

db.test.remove({ “name”:”john” })

MongoDB giriş yazısını burada sonlandırıyorum. Bir sonraki yazımda find ve update komutlarını özelleştiren filtreler ile devam edeceğim.

NoSQL Kavramı

NoSQL(Not only sql, non sql) kavramı,ilişkisel veritabanı yönetim sistemlerinden farklı olan veritabanlar için kullanılır. Google, Facebook ve Amazon gibi büyük şirketlerin ihtiyaçları doğrultusunda kullanımı yaygınlaşmaya başlamıştır.Veri boyutları arttıkça, verilere daha hızlı erişebilmek ve onları daha kolay biçimde tutma ihtiyaçları oluşmuştur.

Sql – NoSQL kıyasları

sql_nosql_2

RDBMSvsNoSQL

Yukarıda belirtildiği gibi NoSQL veritabanlı object oriented tabanlıdır.Esnektir , ölçeklenebilir ve nihai tutarlılığı vardır.Sql veritabanları yapısaldır.

Temel hedeflerinden biri veritabanı tasarımlarının kolaylaşmasıdır. Yapılarına göre 3 tip sınıflandırma yapabiliriz.Doküman tabanlı(document),çizelge(graph) ve Anahtar-değer deposu(key-value) olarak sınıflandırılır.Çeşitli işlemlerin daha hızlı yapılması amaçlanmaktadır.

NoSQL veritabanları büyük veri(big data) ve gerçek zamanlı web uygulamaları(real time web applications) projelerinde sıklıkla kullanılmaya başlanmıştır.

Şimdi NoSQL veritabanlarını inceleyecek olursak;

  • Column: Accumulo, Cassandra, Druid, HBase, Vertica
  • Document(doküman tabanlı): Apache CouchDB, Clusterpoint, Couchbase, DocumentDB, HyperDex, Lotus Notes, MarkLogic, MongoDB, OrientDB, Qizx, RethinkDB
  • Key-value(anahtar-değer): Aerospike, CouchDB, Dynamo, FairCom c-treeACE, FoundationDB, HyperDex, MemcacheDB, MUMPS, Oracle NoSQL Database, OrientDB, Redis, Riak
  • Graph(çizelge): AllegroGraph, InfiniteGraph, MarkLogic, Neo4J, OrientDB, Virtuoso, Stardog
  • Multi-model: Alchemy Database, ArangoDB, CortexDB, FoundationDB, MarkLogic, OrientDB

NoSQL veritabanı türlerinin performans tablosu

nosqlperformance

NoSQL veritabanlarında sql veritabanlarında kullanılan join yapısı bulunmamaktadır.Join yapısı yerine 3 farklı yöntem kullanılabilir.

  • Multiple Queries(çoklu sorgu): İstenilen veriyi tek bir sorguda getirmek yerine çoklu sorgular yaparak getirebiliriz.NoSQL veritabanlarında sorgu yapmak daha hızlıdır.Bu sebeple belli sayıda çoklu sorgu kullanarak istenilen veriyi elde edebiliriz.
  • Caching/Replication: Bu yöntem genellikle okuma işlemlerinin fazla olduğu durumlarda kullanışlıdır.
  • Nesting data(iç içe veri): Genelde doküman tabanlı MongoDB’de çok kullanılan bir yöntemdir.Gerekli olan veriler tek bir dokümanda tutulur.Örneğin blog yazılarını tutan bir doküman içinde,o blog posta ait olan etiketleri ve yorumları tek bir doküman içerisinde tutabiliriz.

Yukarıda söylediğim örneğe yönelik örnek yapı aşağıda gösterilmiştir.Blog post dokümanı içerisinde etiketler ve yorumları aynı yerde tutulmaktadır.Bu yapıya MongoDB yazılarını yazdığım zaman daha detaylı değineceğim.

Günümüzde en çok kullanılan ve en yaygın olan NoSQL veritabanı çözümü document-oriented tabanlı olan MongoDB’dir. MongoDB üzerine daha detaylı makaleler ve örnekler paylaşıyor olacağım.

Daha detaylı bilgileri aşağıdaki sitelerde bulabilirsiniz.

NoSQLMartin fowlermongodb-nosql

Ayrıca Martin Fowler’ın nosql kavramını anlattığı bir konferans