C# ile ElasticSearch Kullanımı: Güçlü Arama ve Analitik Yetenekleriyle Veritabanı İşlemlerini İyileştirmek

Samet UCA
6 min readJul 19, 2023

--

Image Source : https://commons.wikimedia.org/wiki/File:Elasticsearch_logo.svg

Elasticsearch

Elasticsearch’e baktığımızda açık kaynaklı arama ve analiz motoru olduğunu görüyoruz.

Kullanım senaryolarında, büyük miktardaki verileri hızlı bir şekilde depolamamıza, aramamıza ve analiz etmek olabilir. Özellikle büyük ölçekli veri arama senaryoları için kullanılır.

Çalışma Mantığı

Elasticsearch’in çalışma mantığı, bir dizi belgeyi alıp bunları bir indeks içinde depolamasına dayanır. Her belgenin birden çok alanı olabilir ve Elasticsearch, bu alanlara hızlı bir şekilde erişim sağlamak için bir ters indeksleme yapısı kullanır.

Ters İndeksleme

Image Source : https://codingexplained.com/coding/elasticsearch/understanding-the-inverted-index-in-elasticsearch

Ters indeksleme, veri depolama ve arama süreçlerini optimize etmek için kullanılan bir yöntemdir. Geleneksel bir indeksleme yönteminin tersine, ters indeksleme, her bir terimin hangi belgede bulunduğunu takip etmek için bir veri yapısı kullanır.

Bir belgenin içeriğini indekslemek için, ters indeksleme işleminde şu adımlar izlenecektir.

  1. Belgenin içeriği parçalara ayrılır. Örneğin, bir cümledeki her kelime ayrı bir terim olarak kabul edilir.
  2. Her terim, hangi belgede bulunduğunu referans etmek için bir veri yapısı içinde saklanır.
  3. Veri yapısında, her terimle ilişkili belgelerin listesi tutulur. Bu liste, ilgili belgenin konumunu veya diğer bilgilerini içerebilir.

Ters indeksleme, arama sorgularını hızlandırmak için kullanılır. Arama sırasında, istenen terimlerle eşleşen belgelerin listesine hızlı bir şekilde erişilir ve döndürülebilir. Ters indeksleme ayrıca arama sorgularında filtreleme, sıralama ve diğer işlemleri de kolaylaştırır.

Image Source : https://www.knowi.com/blog/what-is-elastic-search/

Bu açıklama yeterli olmadı mı? O zaman kısa bir ara verip şu makaleyi okuyabilirsiniz.

https://codingexplained.com/coding/elasticsearch/understanding-the-inverted-index-in-elasticsearch

Devam edersek, yeni başlayanlar için, Elasticsearch’i şu şekilde düşünebilirsiniz:

Bir kitaplığa benzer. Kitaplığınızda birçok kitap bulunur ve bu kitapların içindeki bilgilere hızlı bir şekilde erişmek istersiniz. Elasticsearch, kitapların dizinlenmiş bir sıralama ve kategorilendirme sistemine sahip olduğu bir kitaplık gibidir. İstediğiniz bilgiyi hızlıca bulabilir ve aradığınızı bulmanızı kolaylaştırır.

Elasticsearch, genellikle büyük ölçekli veritabanları, web siteleri, uygulamalar ve log analizleri gibi veri yoğun alanlarda kullanılır. Verileri kolayca arayabilir, filtreleyebilir ve sıralayabilirsiniz.

Elasticsearch, dağıtık bir yapıya sahiptir, bu da performansı ve ölçeklenebilirliği artırır. Verilerinizi birden fazla sunucuda saklayabilir ve yüksek kullanılabilirlik sağlayabilirsiniz.

Özetlemek gerekirse, Elasticsearch büyük miktardaki verileri hızlı bir şekilde aramanıza, analiz etmenize ve keşfetmenize olanak tanıyan açık kaynaklı bir arama ve analiz motorudur. Verileri düzenlemek, aramak ve analiz etmek için kullanışlıdır ve genellikle büyük ölçekli veritabanları ve analitik senaryolarında kullanılır.

Elasticsearch Kurulum

Projemizde elasticsearch kullanmak için ilk olarak resmi web sitesinden indirmemiz gerekmekte.

https://artifacts.elastic.co/downloads/elasticsearch/elasticsearch-8.8.2-windows-x86_64.zip

İndirilen dosyayı arşiveden çıkarın.

Arşiveden çıkarılan klasörün içerisindeki config klasörüne gidin.

elasticsearch.yaml dosyasını bir metin editörü ile açın.

xpack.security.enabled: true

satırını

xpack.security.enabled: false

olarak değiştirin.

Bu durumda elasticSearch kimlik doğrulama işlemini atlamış olacağız. Bunu yapmamızın sebebi bu anlatımın henüz giriş seviyesinde olmasından dolayı güvenlik aşamalarının ilerleyen seviyelere uygun olması.

Şimdi tekrar elasticsearch anaklasörüne gidin ve bin klasörünü açın.

Resimde işaretlediğim elasticsearch.bat dosyasını yönetici olarak çalıştırınız.

Kısa bir süre yükleme gerçekleşecek ve http://localhost:9200 adresine erişim hazır olacaktır.

Bu adrese gittiğinizde şu JSON verisi ile karşılaşıyorsanız kurulum sorunsuz gerçekleşmiştir.

Elasticsearch sistem kurulumu tamamlandığına göre artık uygulama geliştirme tarafına geçebiliriz.

Uygulama Geliştirme

Visual Studio IDE üzerinden çalışma yapacağım. Eğer siz farklı bir IDE kullanıyorsanız orada Console APP üretmeniz ilk aşama için yeterli.

Proje oluşturulduktan sonra elasticsearch ile iletişim kurabilmek için gerekli bir paket kurmamız lazım.

NEST Paketi Nedir? Ne İşe Yarar?

NEST, Elasticsearch ile etkileşimde bulunmak için kullanılan resmi bir .NET istemci kitaplığıdır. Elasticsearch ile veri indeksleme, sorgulama, güncelleme, silme gibi işlemleri gerçekleştirmenizi sağlar.

NEST, Elasticsearch sorgularınızı ve veri işlemlerinizi daha kolay bir şekilde yapabilirsiniz. NEST, C#’ın özelliklerinden yararlanarak Elasticsearch ile etkileşimi basitleştirir ve daha okunabilir ve sürdürülebilir kod yazmanıza olanak tanır.

NEST Kurulum

Projede kullanacağınız NuGet paketlerini yönetmek için NuGet Paket Yöneticisi’ni açın.

  • Visual Studio’da “Tools” menüsünden “NuGet Package Manager” seçeneğini seçin ve ardından “Manage NuGet Packages for Solution” seçeneğini tıklayın.
  1. NuGet Paket Yöneticisi’nde, “Browse” sekmesine geçin.
  2. Arama kutusuna “NEST” yazın ve arama yapın.
  3. Sonuçlar arasından “NEST” paketini bulun ve “Install” (Yükle) düğmesine tıklayın.

Kodlama kısmında satır satır ne yapabileceğimize bir bakalım.

İlk olarak paket kurulumundan sonra bir node üretip elasticsearch sunucusuna erişim sağlayacak temsili bir nesne olmalı.

 var node = new Uri("http://localhost:9200");

Bir sonraki satırda ihtiyacımız olan URI nesnesini kullanarak bir ConnectionSettings nesnesi oluşturmak.

ConnectionSettings

ConnectionSettings, Elasticsearch istemcisine bağlantı ayarlarını sağlar

Bu nesne ile belirtilen Uri, elasticsearch sunucusuna bağlanır.

var settings = new ConnectionSettings(node)

Noktalı virgülü unuttumuğumu düşünmeyin bu kodun devamında çeşitli set işlemleri yapacağız.

Bir sonraki satırda Elasticsearch için varsayılan dizini “sametuca-medium” olarak ayarlıyoruz. Bu, Elasticsearch sunucusunda yapılan birçok işlemde varsayılan dizinin bu değeri kullanacağı anlamına gelir.

 .DefaultIndex("sametuca-medium")

Bir satır aşağı inerek “DisableDirectStreaming” yöntemi çağrılarak doğrudan akışı devre dışı bırakır. Bu, Elasticsearch ile iletişimde doğrudan akışın kullanılmayacağı ve istemcinin verileri tamponlayacağı anlamına gelir.

.DisableDirectStreaming();

Şimdi şuana kadar yazdığımız koda bir bakarsak;

var node = new Uri("http://localhost:9200");
var settings = new ConnectionSettings(node)
.DefaultIndex("sametuca-medium")
.DisableDirectStreaming();

Şimdi bize lazım olan ConnectionSettings nesnesini kullanarak bir elasticClient nesnesi oluşturmak. Bu nesne elasticsearch ile etkileşim için gereklidir.

var client = new ElasticClient(settings);

Bir sonraki adımda artık elasticsearch tarafına gönderilecek belgeyi oluşturmamız gerkeiyor.

Bu belge elasticsearch’e gönderilecek verileri temsi edecektir.

 var document = new MyDocument
{
Id = 1,
Title = "Örnek Belge 1",
Content = "Elasticsearch medium makalesi için örnek - sametuca"
};

Bir sonraki adımda daha önce oluşturduğumuz client örneği ile document adlı belgeyi elasticsearch’e ekleyeceğiz.

var indexResponse = client.IndexDocument(document);

IndexDocument fonksiyonu, parametre olarak dizine eklenecek belgeyi alır ve geriye bir IndexResponse döner. Bu response üzerinden belgenin eklenip eklenmediğini öğrenebiliriz.

client.IndexDocument(document);
yöntemi aracılığıyla gönderilen belge JSON formatında Elasticsearch'e iletilir.

Bunun dışında eklenirken bir problem yaşarsak bununla ilgili detaylarıda içerecektir.

if (indexResponse.IsValid)
{
Console.WriteLine("Belge başarıyla indekslendi.");
}
else
{
Console.WriteLine("Belge indekslenirken hata oluştu: " + indexResponse.DebugInformation);
}

indexResponse.IsValid kontrolüyle işlemin sonucuna göre aksiyon alabiliriz.

Bu aşamadan sonra bir sorun olmazsa belge eklenecektir. Peki belge eklendikten sonra bu belge için bir query yazabilirmiyiz?

var searchResponse = client.Search<MyDocument>(s => s
.Index("sametuca-medium")
.Query(q => q
.Match(m => m
.Field(f => f.Title)
.Query("Elasticsearch medium makalesi için örnek - sametuca")
)
)
);

Kodu incelediğimizde “sametuca-medium” dizinindeki Title alanında "Elasticsearch" kelimesiyle eşleşen belgeleri arıyoruz. Arama sonucu, nesne olarak döndürülür. Bu nesne, Elasticsearch'ten dönen arama sonucunu içermektedir.

if (searchResponse.IsValid)
{
Console.WriteLine("Arama sonuçları:");
foreach (var hit in searchResponse.Hits)
{
Console.WriteLine("Id: " + hit.Id);
Console.WriteLine("Content: " + hit.Source.Content);
Console.WriteLine();
}
}
else
{
Console.WriteLine("Arama yapılırken hata oluştu: " + searchResponse.DebugInformation);
}

Console.ReadLine();

sorguda problem yoksa searchResponse nesnesinin Hits özelliğini kontrol ediyoruz.

Hits

Hits, Elasticsearch’ten dönen arama sonuçlarını temsil eden bir özelliktir. ISearchResponse<T> arayüzünde bulunur.

Uygulama kodları hazır ise artık çalıştırabiliriz. Sonuç aşağıdaki gibi görünecektir.

Kodların tamamı ise şu şekildedir.

using Nest;

namespace elasticsearch_dotnet
{
public class MyDocument
{
public int Id { get; set; }
public string Title { get; set; }
public string Content { get; set; }
}
internal class Program
{
static void Main(string[] args)
{
var node = new Uri("http://localhost:9200");
var settings = new ConnectionSettings(node)
.DefaultIndex("sametuca-medium")
.DisableDirectStreaming();
var client = new ElasticClient(settings);

var document = new MyDocument
{
Id = 1,
Title = "Örnek Belge 1",
Content = "Elasticsearch medium makalesi için örnek - sametuca"
};


var indexResponse = client.IndexDocument(document);

if (indexResponse.IsValid)
{
Console.WriteLine("Belge başarıyla indekslendi.");
}
else
{
Console.WriteLine("Belge indekslenirken hata oluştu: " + indexResponse.DebugInformation);
}


var searchResponse = client.Search<MyDocument>(s => s
.Index("sametuca-medium")
.Query(q => q
.Match(m => m
.Field(f => f.Title)
.Query("Elasticsearch medium makalesi için örnek - sametuca")
)
)
);

//bir hata olduğunda detaylı bilgi alabiliriz.
//var res = searchResponse.DebugInformation;
//Console.WriteLine(res);

if (searchResponse.IsValid)
{
Console.WriteLine("Arama sonuçları:");
foreach (var hit in searchResponse.Hits)
{
Console.WriteLine("Id: " + hit.Id);
Console.WriteLine("Content: " + hit.Source.Content);
Console.WriteLine();
}
}
else
{
Console.WriteLine("Arama yapılırken hata oluştu: " + searchResponse.DebugInformation);
}

Console.ReadLine();
}
}
}

Projenin kaynağına buradan ulaşabilirsiniz.

Bu makale yazılırken yararlanılan kaynaklar
https://www.elastic.co/guide/en/elasticsearch/reference/current/elasticsearch-intro.html

https://codingexplained.com/coding/elasticsearch/understanding-the-inverted-index-in-elasticsearch

--

--

Samet UCA
Samet UCA

Responses (1)