ElasticSearch ile Arayan Bulur

Adil Deveci
Doğuş Teknoloji
Published in
6 min readFeb 24, 2022

Yıllar önce yapmaya çalıştığım ama başarısızlıkla sonuçlanan bir “site içi arama” hikayesini sizlerle paylaşmak istiyorum. Elimizde halihazırda yayında olan ve içinde birçok ilan bulunan sahibinden benzeri bir web projesi vardı ve bu projeye gelişmiş bir site içi arama özelliğinin eklenmesi isteniyordu(sahibinden ile aynı). Bu iş ilk başlarda kolay gibi görünmüştü. Sql’de birkaç like ile halledemeyeceğimiz şey yok diye düşünüyordum ama yanıldığımı anlamam uzun sürmedi. Yarım sayfa sql sorgusu ile başlayan maceramız boyu 2–3 sayfaya ulaşan sql sorgusu ile devam etti. Sorgu büyüdükçe karmaşıklaşıyor ve performans sorunları da beraberinde geliyordu. Artık performansı değil doğru sonuç gelsin de performansı bir şekilde hallederiz gibi düşünceler oluşmaya başlamıştı. Sorunla birkaç gün uğraştık ve birkaç sayfalık sql sorgusu sonucunda yaptığımız arama sayfasına gelen sonuçların müşterinin hiçbir isteğini karşılamadığını anladık. Performans problemlerinden bahsetmiyorum. Tabi o zamanlar elasticSearch var ama kullanmayı bilmediğimiz için hiç yeltenmedik bile :) Sonuç olarak verdiğimiz tüm emekler çöp oldu. Hikaye bu kadar :)

Makalenin geri kalan kısmında elasticSearch hakkında detaylı bilgiler vererek belki birkaç arkadaşı aynı hataya düşmekten kurtarabilirim diye düşünüyorum :)

Elasticsearch, Apache Lucene altyapısı üzerinde kurgulanan, Java programlama dili ile geliştirilen, açık kaynak bir metin arama moturu ve analiz aracıdır. Lucene’nin anlık veri grupları ve dağıtık sistemler içerisinde yapılan aramalarda yetersiz kalması sonucunda doğan ihtiyaçla, Elasticsearch ortaya çıkmıştır. Elasticsearch, esnek çalışma yapısı ve dağıtık tüm sistemlerde gerçek zamanlı olarak veriler üzerinde işlem yapabilmesi gibi birçok özelliği ile kısa sürede popüler olmuştur. Asıl amacı arama hizmeti vermek olsa da çok kez işlem log’larının saklanması amacı ile normal bir veri tabanı gibi kullanıldığını da gözlemleriz. Kibana ara yüzü sayesinde log bilgilerinin görselleştirilmesinde de kolaylık sağlamakta. ElasticSearch kullanan firmaların bazılarını buradan görebilirsiniz.

Elasticsearch Avantajları

  • Yüksek ölçeklenebilir ve dağıtık yapılar üzerinde çalışabilme kapasitesindedir
  • Açık kaynaklıdır
  • Restful API desteği vardır
  • Gerçek anlamda eş zamanlı çalışır. Veriler kaydedildikten hemen sonra Elasticsearch aramalarında listelenmektedir
  • Yedekleme süreçleri hızlı ve kolaydır
  • Az kaynak kullanımı ile çalışmaktadır
  • Sade bir Cluster yapısı vardır
  • İndeksleme özelliği ile arama sonuçları hızlı bir şekilde iletilmektedir
  • Dokümanlar JSON formatında indekslenir
  • Veri tipine özel Mapping yapabilmektedir
  • Kurulumu hızlı ve kolaydır

Full-text search (Tam metin arama)

Herhangi bir kaynaktan alınan metin belgeleri içinden, herhangi bir anahtar kelimenin aratılmasıyla, anahtar kelime ile eşleşen dokümanların bulduğu sonuca hızlı şekilde erişime verilen isimdir.

Örneğin, wikipedia.com sitesinde bir kelime aratıp bununla ilgili yazılan yazıları okuyacağınızı varsayalım.

Wikipedia’nın arama çubuğuna Alan Turing yazdığınızda onunla ilgili yazıları bulmak için kayıtlı tüm yazılarda arama yapmak yerine, önceden indexlenmiş veriler içinden Alan Turing ’in adının geçtiği metinlerin olduğu index’e hemen gidip hızlıca size sonuç döndürmeyi sağlayan yapıdır.

Temel ElasticSearch Kavramları

Indice

İlişkisel veri tabanlarında veri tabanı yerine Elasticsearch’de Indice kavramı kullanılmaktadır. Bir Elasticsearch Cluster’ı birden fazla index bulundurabilir.

Type(Tablo)

İlişkisel veri tabanlarındaki tablolara karşılık burada “Type” kavramı kullanılır. Bir indice, birden fazla tablo barındırabilir, fakat bu özellik son sürümlerde desteklenmemeye başlamıştır.

Document(Doküman)

Elasticsearch’te, ilişkisel veri tabanlarındaki Rows (satılar), Documents olarak temsil edilirler. Her type, birden fazla document nesnesine sahip olabilir.

Field(Column)

Klasik veritabanlarındaki Column’lar, Elasticsearch’te Field olarak nitelendirilir. Her document bir den fazla field’a sahiptir.

Index

Elasticsearch’e eklenen her kayıt JSON belgesi olarak yapılandırılır. Bu sebeple, dokümanlarınızın içindeki her bir kelime(terim) için hangi doküman ya da dokümanlarda o kelimenin olduğu bilgisini tutan bir indeksleme sistemi vardır. Bu sistemi veritabanı gibi düşünebilirsiniz. Veri tabanındaki verilerde olan düzen gibi, Elasticsearch’ün indexleri de JSON formatı şeklinde düzenlidir.

Mapping

Verileri indekslerken bu verilerin hangi tipte olduğunu belirtmemiz gerekir. Yani o kelimenin hangi veri tipinde(string, integer, boolean) olduğu bilgisinin tanımlandığı işlemdir.

Near Realtime(Yakın Gerçek Zamanlı)

Elasticsearch gerçek zamana yakın bir hızla çalışır. Gerçek zamanlı yerine “yakın gerçek zamanlı” denmesindeki sebep, bir dokümanı, gerçek zamandan çok az farklı bir gecikme süresi ile indexlenmesidir.(Bu süre genelde bir saniyelik bir gecikme oluyor.)

Cluster

Tüm verilerinizi bir arada tutan ve tüm indeksleme ve arama yeteneklerinin yürütüldüğü birden çok node’dan oluşan bir küme veya node koleksiyonu şeklinde adlandırılabilir.

Bir küme, varsayılan olarak “elasticsearch” şeklinde benzersiz bir adla tanımlanır. Bu isimlendirme isteğe bağlı olarak değiştirilebilir. İsimlendirmeler önemlidir çünkü bir node yalnızca bir cluster’ın parçası olabilir. Node, cluster adıyla kümeye katılmak için ayarlanmışsa bu isim tanımlamalarının doğruluğuna ihtiyaç olacaktır.

Node

Tek bir server’a verilen isimdir. Verilerin depolandığı makinelerin her biridir. Clusterların indexleme ve arama yetenekleri bu nodelar sayesinde gerçekleşir. Clusterlardaki isimlendirme mantığındaki gibi nodelara da başlangıçta benzersiz bir id atanır(Universally Unique IDentifier-UUID). Bu isimlendirmeler, nodelar arasındaki bilgi alışverişinin yönetimi için oldukça önemlidir. Eğer istenirse bu isimler de değiştirilebilir. Varsayılan olarak her node “elasticsearch” şeklinde isimlendirilen bir cluster’da çalışmak üzere ayarlanmıştır. Hangi node’un hangi cluster’a gitmesini isterseniz, o cluster ismine yönlendirmelisiniz.

Shard

Bir indeks, daha küçük parçalar olan shard’lara bölünür. Shard’lar, verilerin dağıtık bir ortamda depolanmasını ve işlenmesini sağlar. Bir shard, temel olarak bir indeksin alt kümesidir.

Tek seferde milyonlarca dokümanı indekslemek için yeterli donanıma/server kapasitesine sahip olamayabiliriz. Tek seferde 2TB lık veriyi indekslemek zorunda kaldığınızı varsayalım, bu durumda bu indekslemeyi tek bir node ile yapmak istediğinizde, disk kapasitesinin dolması veya aşırı yavaş bir indeksleme hızı ile karşı karşıya kalabilirsiniz. Bunun önüne geçmek için Shard ve Replika kavramları bulunmaktadır. Yapılacak olan bir index, bir node da yeniden shardlara bölünür. Bu shardları kendinize göre ayarlayabilirsiniz.

Replica

Tamamen güvenlik amaçlı çalışan, her verinin bir kopyasının bulunduğu başka makinelerdir. Böylece bir makine çöktüğünde replica veya replicalarından biri devreye girebilecektir. Örneğin aşağıda 3 Node’lu 3 Shardingli bir yapı söz konusudur. Her bir shard’ın 1 yedeği, yani 1 replicası bulunmaktadır. Sonuçta aşağıdaki örnekte 3 Node, 3 Shard ve 1 Replica mevcuttur. Toplamda 6 sunucu bulunmaktadır.

ElasticSearch Kullanım

Bu kadar teorik bilgi sonrasında birkaç örnek ile bilgilerimizi pekiştirelim.

Elasticsearch’ün RestfulAPI desteği olduğu için herhangi bir restFull hizmeti veren uygulamadan http istekleri göndererek işlemlerinizi yapabilmeniz mümkündür. Ben örnek çalışmalarımı postman uygulaması üzerinden yapacağım. Ayrıca Kibana Console üzerinden de sorgular çalıştırılabilir.

Eğer siz elasticsearch’ü bir uygulama üzerinden çağıracaksanız, ilgili uygulamadan elasticSearch’e rest api çağrıları yapabilirsiniz.

Not: Bu yazıda elastic search ve kibana kurulumu hakkında bilgi verilmeyecektir, bunların kurulmuş olduğunu varsayarak devam ediyorum

Not: {{baseUrl}} benim kullandığım elastic adresini içermektedir. Siz çalışma yapacağınız elastic sunucusunun adresini girip örnekleri uyguyalabilirsiniz. (Örneğin: http:// localhost:9200)

.Net Nest Kütüphanesi Hakkında

.Net geliştiricileri için kolaylık sağlama amacı ile NEST kütüphanesi bulunmakta. İster nest kütüphanesinin metotlarından yararlanarak elastic ile haberleşin ister direkt http çağrısı yapın. Burada dikkat etmeniz gereken nokta; kurulmuş olan elasticSearch versiyonu ile Nest versiyonunun uyumlu olmasıdır. Eğer Legacy bir projede çalışıyorsanız ve sunucunuzda ElasticSearch son sürüm kurulu olmasına rağmen bağımlılıklardan dolayı Nest’in son versiyonunu projenize yükleyemiyorsanız, bu durumda Nest kütüphanesinin metotları tam uyumlu çalışmayacak ve bazı metotlarda hata alınacaktır. Tecrübe ile sabittir ;)

Index Yaratma

Basit index yaratma

Aşağıdaki istek hiçbir ayarlama yapmadan en basit haliyle bir index yaratabilirsiniz. İşlem sonucunda Customernames adında bir index yaratılmış olacak.

Put Request:

{{baseUrl}}/customernames/

Index Ayarları

Aşağıdaki istekte index yaratılırken kaç shard ve kaç replica olacağını body kımındaki JSON içeriğinde belirtmekteyiz.

PUT: {{baseUrl}}/customernames/

request body

Gelişmiş bir örnek

Aşağıda kendi çalışmama ait ufak bir örnek vermek istiyorum. Bu örnekte analyzer, search_analyzer, mapping, stop word gibi özellikler kullanılmıştır. Türkçe karakterler, büyük küçük harf ve boşlukların problem olmaması için filter özelliği kullanılmıştır. CustomerName, CompanyName alanlarına ayrı ayrı farklı özelliklerde analyzer enstrümanları uygulanmıştır. AutoComplete aramaları için edge_ngram_analyzer kullanılmıştır.

request body

Index Silme

Aşağıdaki delete isteği ile mevcut bir indexi tamamen silebilirsiniz.

DELETE: {{baseUrl}}/customernames

Kayıt Silme

Aşağıdaki istek ile mevcut bir index’deki tüm kayıtları silebilirsiniz.

POST: {{baseUrl}}/customernames/_delete_by_query

request body

Faydalı Bazı Sorgular

GET Settings

Aşağıdaki sorgu ile index durumu hakkında bilgi alınabilir.

GET: {{baseUrl}}/customernames/_settings?pretty

response

GET Mapping

Aşağıdaki sorgu ile mevcut bir index’inize ait mapping bilgilerini alabilirsiniz. Örnek olaması için ben kendi çalışmama ait bir indeksin mapping bilgisini ekliyorum.

GET: {{baseUrl}}/vdfcustomer-db/_mapping?pretty

response

POST Analyze

Analyze sorguları ile hangi analyzer’ın kelimeleri nasıl indexleyeceğini test edebilirsiniz.

Örnek 1

Daha önceden oluşturduğum name_analyzer kullanıldığında kendi adımın nasıl indekslenmiş olduğun bir bakalım.

POST: {{baseUrl}}/vdfcustomer-db/_analyze

request body
response

Örnek 2

AutoComplate için yazmış olduğum edge_ngram_analyzer’ı kullanarak kendi adımı nasıl indeksleyeceğini görelim.

POST: {{baseUrl}}/vdfcustomer-db/_analyze

request body
response body

Search Example

Nihayet sonuca gelebildik. Burada daha önceden oluşturduğum ve içine verileri yüklediğim bir index üzerinde arama işlemi yapacağız. Arama ile alakalı bir çok örnek mevcut. Tek alan üzerinde arama yapılabilir, birden fazla alanda arama yapılabilir, ve-veya gibi mantıksal koşullar eklenebilir vs.

Autocomplete işlemi için hazırladığım sorgu ve sonucunu paylaşmak istiyorum. Bu sorgu hem müşteri adında hem de firma adında arama yapıyor. Aynı zamanda sadece belongsTo=Vdf olan kayıtları getirmesi için filtreleme uyguluyor. Arama metninde birden fazla kelime olması durumunda tüm kelimeleri içermesi için “and” operatörü kullanılıyor. Dikkat ederseniz aranan metin ile gelen sonuçlar arasında Türkçe karakter ve büyük küçük harf sorun oluşturmuyor.

Örnek 1

POST: {{baseUrl}}/vdfcustomer-db/_search

request body
response

Örnek 2 Birden fazla kelime ile arama

POST: {{baseUrl}}/vdfcustomer-db/_search

request body
response

Asp.Net AutoComplate from ElasticSearch

Postman üzerinden request atarak elastic search üzerindeki dataları filtreleyerek getirmeyi başardık, peki bunu uygulamamıza nasıl entegre edeceğiz?

Bu çalışmayı ben legacy bir aspnet webform projesinde autocomplate için yapmıştım. AspNet’de autocomplete ile daha önce uğraşanlar konuya hakimdir. Normalda bir textbox için bir WebMethod yazılır ve ajax ile web servise istek atılarak ilgili WebMethod içinden direkt db’deki veriler süzülerek getirilirdi. ElasticSearch kullandığımız senaryoda ise DB’yi aradan çıkartıyoruz. Arama kutusunda metin değiştiğinde WebMethod içinden direkt HttpClient ile ElasticSearch sunucusuna request atıyoruz. Json formatında aldığımız dataları autocomplete’de göstermek için uygun hale getiriyoruz ve işimiz bitiyor :)

ElasticSearch request for autoComplete data
Call WebMethod from aspx

Bu örnekler üzerinden giderek isterseniz benim gibi müşteri adı arama kısmına autocomple yazarsınız, isterseniz site içi arama yaparsınız. ElasticSearch’ün henüz keşfetmediğim bir çok farklı özelliği bulunmakta :) Ama bir SearchEngine’e ihtiyacınız varsa kesinlikle doğru bir araç olduğunu söyleyebilirim :)
Bir yazımızın daha sonuna geldik, hoşça kalın :)

--

--