ElasticSearch Nedir?

Selamlar,

Bugün ElasticSearch üzerine bolca konuşacağız:

ElasticSearch, BigData yani büyük veriler ile çalışan şirketlerin, adından da anlaşılacağı gibi içerik arama, veri analizi, soruglamalar ve öneriler gibi işlemlerde özellikle performans kabiliyetleri, güçlü ve esnek olmasından dolayı tercih ettiği bir search engine’dir. Kimdir bu büyük şirketler LinkedIn, Stack Overflow, Foursquare, GitHub, Amazon gibi. ElasticSearch, java dili ile geliştirilmiş, “Lucene” altyapısı üzerine oturtulmuş open-source bir arama motorudur. Tabi ki boşuna bu dev teknoloji şirketleri tarafından kullanılmamaktadır.

Visual Studio .Net tarafında NEST kütüpahanesi ile bu güçlü arama motoru kolayca implemente edilebilmektedir. Öncelikle nereden indirilir. Benim tercihim : http://ruilopes.com/elasticsearch-setup/ buradan ilgili GitHub reposuna gidip indirebilirsiniz. Bu makalede v5.1.1’i versiyonu kullanılmıştır.

İlgili ElasticSearch setup.exe kurulduktan sonra, windows makinasındaki servisler kısmına “Windows+R” ile run command satırı açılıp, “services.msc” komutu yazılarak erişilir. Buradan aşağıda görülen Elasticsearch Servisi manuel olarak çalıştırılır.

Ben ayrıca gelen json datayı Chrome browser’da düzgün göstermek için “JSON Viewer” extension’ını kullandım. Size de özellikle ElasticSearch ile çalışırken kurmanızı tavsiye ederim. İlgili servis çalıştırıldıktan sonra http://localhost:9200/  adresine gidildiğinde aşağıdaki gibi bir ekran ile karşılaşılır.

Son olarak browser üzerinde post ve get işlemleri yapmak için ben Chrome Extension olarak Postman kurdum. Size de tavsiye ederim.

Ayrıca isterseniz ElasticSearch ile uğraşanların bolca kullandığı Kibana ve monitor tool’u olan Malware’i de buradan  kurabilirsiniz. Ben bu makalede bu tooları kullanmayacağım. Tüm işlemleri Postman ve Visual Studio idesi üzerinden yapacağım.

Index: Öncelikle ElasticSearch’de her kayıt bir Json dökümandır. Yani indexler, Json belgeler topluluğudur. Default veya Custom olarak yaratılabilirler.  Yeni bir index yaratma sırasında, alias vermek çok sağlıklıdır. Alies verildiği takdirde, indexde olan bir değişiklikten dolayı yeni bir index yaratılıp eskisi kolaylıkla silinebilir. Kısaca her bir index bir çeşit veritabanıdır.

Mapping: Bir veri şablonu ya da data modeli olarak da tarif edebiliriz. Amacı, ilgili dökümanın arama motoruna nasıl aktarılacağının tanımlanmasıdır. Kısaca veritabanında isimlendirdiğimiz bir schema’dır diyebiliriz.

Document: ElasticSearch’deki her bir kayda, yani row’a document denir.

Field: Her bir döküman içindeki alana, field denir. Yani DB’deki bildiğiniz column.

Post.cs: Aşağıda, Mapping’imiz olan bir Post sınıfı tanımlanmıştır. Yani arama işlemi yapılacak data scheması, aşağıdaki gibidir.

Create Index: Aşağıda “NEST” kütüpahanesi kullanılarak,  “blog_history” adında bir index yaratılmıştır. Aliases verilmiş ve ilgili index’e ‘bora_blog‘ şeklinde de erişilebilmesi sağlanmıştır. ElasticSearch’e erişilen url :”http://localhost:9200″ “ConnectionSettings” sınıfında tanıtılmıştır. Ve ilgili “ElasticClient” tanımlanan url ile oluşturulup ilgili index “CreateIndex()” methodu ile yaratılmıştır.

Bu işlemden sonra  “http://localhost:9200/_cat/indices” yazıldığında yaratılan indexlerin tamamı görülebilir.

Yine DefaultIndex, Alies verilmeden “MapDefaultTypeIndices()” methodu ile de aşağıdaki gibi oluşturulabilir.

Peki ElasticSearch bu armayı bu kadar hızlı nasıl yapıyor : Bir veri yani document kaydedilirken, veri içerisindeki alanlar yani fieldlar “Apache Lucene” altyapısı kullanılarak indexlenir. Bu şekilde bir kelimenin hangi row’da yani document’da geçtiği indexlenir. Daha sonra ilgili keyword aranırken bu büyük veri kümesi içerisinde değil de, bu oluşturulan index listesi içerisinde arama yapılır.  Böylece istenen arama sonucuna, çok büyük bir hızda ulaşılabilir.

Aşağıdaki örnekde: 6 farklı document ve her bir kelimenin geçtiği row sırası ayrı ayrı indexlenerek kaydedilmiştir. Örneğin “night” kelimesi <1>, <4> ve <5> inci rowlarda geçmektedir. Kısaca “night” kelimesini ElasticSearch ile aradığımızda ilgili kümülatif data içerisinde değil de, bu örnekde olduğu gibi önceden tanımlanmış aşağıdaki index listesi içinde aranmakta ve çok daha hızlı bir şekilde bulunabilmektedir.

 

Peki yüksek trafik durumları için ElasticSearch’de neler yapmalıyız: Burada öncelikle, Nodelar ve Sharding devreye giriyor.  Nodelar’ın her birinde 1 tane ElasticSearch çalışır. Her bir node, tüm indexleme ve okuma işlerinde birbirleri ile haberleşir. Tüm Nodelar, “Cluster” dediğimiz sunucu kümeleri içinde bulunur. Shardlar ise, Nodelar içerisinde verilerin indexlenmesini sağlıyan “Apache Lucene” uygulamaının ta kendisidir. Mesela aşağıdaki resimde 2 Node ve 4 Sharding’li bir yapı görülmektedir.

Image Source: https://skelia.com/wp-content/uploads/2014/06/table.png

Peki Makinalardan Biri Çöker İse: (Replica) Tamamen güvenlik amaçlı çalışan, her verinin bir kopyasının bulunduğu başka makinalardır. Böylece bir makina çöktüğünde replica veya replicalarından biri devreye girebilecektir. Örneğin aşağıda 3 Node’lu 3 Shardingli bir yapı söz konusudur. Ve her bir shard’ın 1 yedeği, yani 1 replicası bulunmaktadır. Sonuçta aşağıdaki örnekde 3 Node,3 Shard ve 1 Replica mevcuttur. Toplamda 6 sunucu bulunmaktadır.

NOT:  Bir diğer dikkat edilecek konu da, her bir Shard’ın Replicasının başka bir Node’da bulunması gerektiğidir:) Ben Shard’ın ve Replikasının aynı makina konulduğunu, ve daha sonra makina çökünce tüm indexlerin nasıl kaybolduğuna birebir şahit oldum:)

Image Source: https://elastic-stack.readthedocs.io/en/latest/_images/elk_cluster_shard.png

Peki bu Sharding ve Replica sistem tanımı NEST ile .Net tarafında nasıl kodlanır: Aşağıda görüldüğü gibi “IndexSettings()” methodu ile “NumberOfReplicas” ve “NumberOfShards” sayısı belirlenmiş ve yaratılan Index özelliklerine “InitializeUsing()” methodu ile set edilmiştir.

Gelelim yapılan Postların ElastikSearch’de kaydedilmesine: Aşağıda görüldüğü gibi ilgi postlar oluşturulup “my_blog” index’ine post edilmiştir. Daha sonra ilgili row yani documentler “http://localhost:9200/my_blog/post/_search” şeklinde sorgulanarak ekrana basılmıştır.

Örnek Ekran Çıktısı:

Peki ElasticSearch’de Query nasıl kullanılır : NEST kütüpahanesi kullanılarak ElastickSearch üzerinde Query işlemleri yapmak aslında biraz detaylı bir konu. Konu hakkında fikir sahibi olunması amacı ile birkaç örnek vermek istiyorum:

Örnek 1: Aşağıdaki örnekde “UserID”‘si 2 olan toplam 10 kayıt çekilmektedir. Burada önemli filter keywordlerinden biri “Term“‘dir.

Termler: Sadece boolen yani “Yes/No” veya string bir kelime ile eşleşebilecek durumlarda kullanılır.

Sonuç ekranı aşağıdaki gibidir: Indexlenen documentlardan UserID’si 2 olan tek kayıt geri dönülmüştür. İlgili kayda, geri dönen response’daki documentlere bakılarak erişilir. “response.Documents

Örnek 2: Yukarıdaki örneğe ek olarak “MatchPhrasePrefix()” methodu ile “PostTest” filed’ında “angular” kelimesi geçen kayıtlar(documentlar) da listelenmeye result set’e ulaşılır.

Aşağıdaki sonuçda da görüldüğü gibi hem UserID‘si 2 olan hem de “PostTest” field’ında “angular” kelimesi geçen rowlar bulunmuştur.

Eğer “MatchPhrasePrefix()” methodu yerine “MatchPhrase()” methodu kullanılsa idi “angular” keyword’ü için bir sonuca ulaşılamaz, yalnızca UserID’si 2 olan result set geri dönülürdü. Nedeni “MatchPhrase()” methodu, içinde geçen kelimeye değil, kelimenin tamamının eşleşmesine bakar. Eğer “angular2” kelimesi aransa idi o zaman ilgili kayda ulaşılabilirdi. Belki bazılarınızın dikkatini çekmiştir. Büyük harflerin örnek “Angular2″‘nin küçük harf şeklinde aranması sonucunda bulunabilmiştir. Bu konuyu ilerde Analyzer kısmında inceleyeceğiz.

Filter: İlgili yazılan Querylerin sonuna filterlar eklenip, arama sonucu daha da daraltılabilir. 2 farklı tipi vardır.

  • Filtered: Sorgu çalıştırılırken filitreleme işlemi yapılmaktadır. “Prefilter” gibi düşünülebilir.
  • Filter: Sorgu çalıştırıldıktan sonra dönen sonuç üzerinden, 2. bir işlem olarak gidilmektedir. “Postfilter” gibi düşünülebilir.

Birden fazla filter peş peşe eklenip daha spesifik bir result set’e ulaşılabilir.

Örnek : Aşağıdaki örnekde UserID’si 1 olan ve “PostTest” filed’ında “angular” geçen documentlere ek olarak, “PostFilter()” methodu ile “DateRange” filter eklenmiş ve “PostDate” field’ını “GreaterThanOrEquals()” methodu ile günümüzden 4 gün evelki bir tarihden büyük veya eşit olması koşuluna bakılmıştır.

Aramalarda Vurgu Yapmak Highlight : 

ElasticSearch’de arama yapıldığı zaman, bulunan sonuçların ilgili Query text’in nerelerinde eşlediğinin gösterildiği güzel bir yapıdır.

Örnek Highlight: Aşağıda görüldüğü gibi önce “Query” sonra “Filter” ve daha sonra “Highlight” tanımlanmıştır. 

  • “PreTags”: İlgili filiterlardan sonra bulunan result’ın başına konacak karkter belirlenir.
  • “PostTags”: İlgili filiterlardan sonra bulunan result’ın sonuna konacak karkter belirlenir.
  • “Fields”: Highlight amaçlı bakılacak kolon belirlenir.

İlgili çıktıların alınması için dönüş yani response’un HITS‘lerine bakılır.

HITS Propert’sinden dönen fieldlar:

HITS : Toplam geri dönüş adedine, toplam score’u gibi bilgileri veren, her bir dönen row’un “_id”‘sini, “_Score”‘unu, “Highlights”‘ını ve bunun gibi birçok kritik veriyi dönen çok önemli bir propertydir.

Ekran Çıktısı: Yukarıda görüldüğü gibi dönen result değeri içindeki HITS’ler gezilerek, ilgili Highlights değerleri ekrana bastırılmıştır. Aşağıdaki ekran çıktısında da görüldüğü gibi, aranan “angular” keyword’ü bulunduğu text içerisinde başına ve sonuna belirlenen “<font color=’red’><b> </b></font>” html tagları ile çevrelenmiştir.

Bu makale ile ElasticSearch’e sıkı bir giriş yaptığımız kanısındayım. Aslında ElasticSearch leb i derya bir deniz. İlerleyen zamanlarda bu konu üzerinde yazmaya devam edeceğim. Daha Analyzer, Synonym, Aggregation, Suggesters gibi bahsedilmeyen birçok konu mevcut. Diyip içinize düşürdüğüm bu kurt ile merakınızı ve algınızı maximuma çıkardığımı düşünüyorum :)

Geldik bir makalenin daha sonuna :)

Yeni bir makalede görüşmek üzere hoşçakalın.

Source:

Herkes Görsün:

Bunlar da hoşunuza gidebilir...

36 Cevaplar

  1. mehmet dedi ki:

    merhabalar guzel bir makale
    konu degil ama bana ucretsiz document veya relation db lazim. 5gb lik . Bilgisi olan arkadaslardan destek bekliyorum

  2. Sinan Bozkuş dedi ki:

    Kaliteli bir makale olmuş, elinize sağlık.

  3. Selcan dedi ki:

    Yazdığınız tüm makaleler başarılı. Emeğinize sağlık.

  4. süleyman yalçın dedi ki:

    Elinize sağlık Bora bey.
    Sizce bir projede Cache yapısı(enterprise,memorycache vs..) yerine ElasticSearch kullanılsa mantıklı olurmu?
    Sonucta ElasticSearch da kendi üzerinde cache yapıyor ve anladığım kadarıyla sql sorgularından daha hızlı. Ozaman veri okuma işlemlerimizi direk ElasticSearch üzerinde yapsak ve create,delete,update işlemleri için sadece sql kullansak mantıklı olurmu?

    • borsoft dedi ki:

      Selamlar Süleyman Bey,
      Bu şekilde kullananlar da var. Ama ben kesinlikle onaylamıyorum. Tabiki data çekmek için herzaman Sql’e gitmemelisiniz. Bence Radis gibi bir harici memcache kullanmanız daha performanslı olucaktır. Gerçekten Search işlemi yapacak iseniz o zaman Elastic kullanınız. Analizinize yazık :)

      İyi yıllar iyi çalışmalar.

  5. Burak Kaşıkcı dedi ki:

    Güzel bir makale olmuş, emeğinize sağlık.

    • borsoft dedi ki:

      Teşekkürler Burak. Bu aralar farklı konular ile ilgileniyorum. Ama devamıda gelicek.

  6. Tayfun dedi ki:

    Devamını bekliyoruz hocam. Projelere eklemek için sabırsızlanıyorum :)

  7. Metin dedi ki:

    Çok güzel ve bilgilendirici bir makaleydi. Teşekkürler.

  8. selcuk dedi ki:

    Çok yararlı bir döküman olmuş

  9. Cihan dedi ki:

    Bora hocam, ellerinize sağlık çok güzel bir makele olmuş.
    Devamını bekleriz :)

  10. Barış dedi ki:

    Merhaba, Big data örneği üzerinde ElasticSearch Apache Spark (SparkSQL) farkı nedir acaba? Performans olarak hangisini önerirsiniz.

  11. Ibrahim dedi ki:

    Merhabalar,
    Elinize sağlık,çok güzel bir paylaşım olmuş.

  12. Mustafa dedi ki:

    Makaleniz için teşekkürler.
    Şöyle bir sorum olacak;
    Index dosyalarımızı oluşturduğumuzda
    dosya boyutuna göre mi ölçekleniyor.
    Eğer bu şekilde değilse node sayısını neye göre belirleyebiliriz?
    Teşekkürler.

  13. Ahmet dedi ki:

    Elinize, emeğinize sağlık Bora hocam. Çok faydalı oldu. Ufak bir sorum olacaktı. Örnekte yukarıdan aşağı giderken

    var createIndexDescriptor = new CreateIndexDescriptor(“blog_history”)
    .Mappings(ms => ms
    .Map(m => m.AutoMap())
    )
    .Aliases(a => a.Alias(“bora_blog”));

    şeklinde bir index tanımlaması mevcut. Sonrasında ise default index ile devam etmişsiniz.

    settings.DefaultIndex(“defaultindex”).MapDefaultTypeIndices(m => m.Add(typeof(Post), “my_blog”));

    Burada default ile devam etmeden index oluşturmak için createIndexDescriptor’u nasıl kullanabiliriz?
    Teşekkürler;

    • borsoft dedi ki:

      Selam Ahmet,

      Öncelikle teşekkürler :) .Aliases(a => a.Alias(“bora_blog”)) ile bir index tanımlaması yapılmıyor. Var olan index’e eşlenik isim veriliyor. Böylece ilgili index üzerinde bir işlem yapıldığında alies verilen kolaylıkla silinip yenisi yaratılabiliyor Bir elastic search üzerinde 2 index aşağıdaki gibi yaratılabilir. Tek tek yaratılabilir. Ama çoklu Alias’da yaratabilirsin. O da işini görür :)

      client.CreateIndex(c => c
      .Index(“myindexname”)
      .InitializeUsing(settings)
      );

      Ayrıca tüm indexler ==> GET /_cat/indices?v ya da “localhost:9200/_cat/indices?v”
      Tüm aliesler ==> “http://localhost:9200/_aliases” şeklinde listelenebilir.

      İyi çalışmalar.
      Hoşçakal..

  14. veysel sebu dedi ki:

    elinize sağlık çok güzel ..

  15. Teşekkürler, yararlı bir paylaşım.

  16. Abi eyvallah be çok teşekkür ederim. Bilgi borçlandım, sana ödeyemem belki ama söz senin adına bir başkasına aktarıcam. Çok teşekkür ederim tekrardan .

  17. Mersan reklam dedi ki:

    Hocam senin bütün makalelerin çok güzel eline sağlık saygılarımla

  18. Orkun dedi ki:

    Hocam ufak bir sorum olacaktı;
    public static void CreateNewIndex()
    {
    var createIndexDescriptor = new CreateIndexDescriptor(“blog_history”)
    .Mappings(ms => ms
    .Map(m => m.AutoMap())
    )
    .Aliases(a => a.Alias(“bora_blog”));
    node = new Uri(“http://localhost:9200/”);
    settings = new ConnectionSettings(node);

    client = new ElasticClient(settings);
    var response = client.CreateIndex(createIndexDescriptor);

    }
    Bunu hangi dosya içinde yapıyorsunuz acaba?

  19. Rıdvan Tayfur dedi ki:

    @borsoft selamlar makale çok başarılı eline sağlık benim sormak istediğim şey şu bu elasticsearch uygulamasının backubını alabileceğim uygulama var mı (veeam, netbackup , avamar v.s?) nod mantığıyla v.s

  20. Ali Taş dedi ki:

    Şimdiye kadar okuduğum en faydalı makale oldu teşekkürler

  21. Samet dedi ki:

    Hocam makaleniz çok güzel ve faydalı olmuş teşekkürler.
    Bir sorum olacaktı udemy veya youtube de ELK yi anlatan bir eğitim serisi hazırlayabilir misiniz?
    bu konuda fazla Türkçe kaynak yok öğrenmek isteyenler için çok iyi olur.

Bir cevap yazın

E-posta hesabınız yayımlanmayacak.