Elasticsearch: Postfilter Kullanımı

Yılın son yazısını, en çok okunan yazılarımın öznesi Elasticsearch’e ayırmamak haksızlık olur diye düşündüm ve tabiri caizse hap bir yazı ile bu haksızlığı gidermek üzerine kolları sıvadım.

Elasticsearch üzerine yıl boyunca bir takım kurgularla birlikte yazılar yazdım, bu yazılar içerisinde de ürünün gayesini temel anlamda iletebildiğime inanıyorum. Dolayısıyla bu yazı, hem bir önceki cümlede belirttiğim durum sebebiyle hem de yazının “Temel Reis’in Ispanağı” tadında olmasını planladığımdan ötürü girizgahı kısa kesiyor ve asıl derdimize yönleniyorum.

Amacımız yukarıdaki gibi bir ekran tasarlamak. Özetle, bir takım ürünleri listelemek istiyoruz. Ayrıca listeleme esnasında bir kategoriye göre filtreleme yapılır ise, diğer kategorilerde de kaç adet ürün olduğunu filtre ekranında muhafaza etmek temel koşulumuz.

Önce örneğimizi canlandırabilmek adına temel işlemlerimizi gerçekleştirelim:

docker pull docker.elastic.co/elasticsearch/elasticsearch:5.4.3

komutu ile Docker ortamında kullanmak üzere Elasticsearch image’ını bilgisayarımıza indirelim ve hemen ardından;

docker run --name elastic -d -p 9200:9200 -p 9300:9300 -e "http.host=0.0.0.0" -e "transport.host=127.0.0.1" -e "xpack.security.enabled=false" docker.elastic.co/elasticsearch/elasticsearch:5.4.3

komutunu çalıştırarak, indirdiğimiz image’dan bir container oluşturup çalışır vaziyete getirelim.

Eğer buraya kadar her şey yolunda gitti ise, listeleyeceğimiz ürünleri tutacak bir index’e ihtiyacımız var:

“shopping_index” isimli index’te tutulacak “product” tipindeki nesnelerin “ProductName”, “CategoryId”, ve “Price” adlı üç özelliği bulunuyor. Bu özellikleri üzerinde barındıran örnek kayıtları da eklersek sorgulama için gerekli argümanları oluşturmuş olacağız.

Derde derman arama

Sorgumuz için kriterimiz aslında oldukça basit. CategoryId değeri 3'e eşit olan kayıtları listeleyecek bir sorgu yazacağız. Ayrıca bu sorgudan gelen cevaba bir de kategorilerin ve kategorilere ait ürünlerin sayılarının yer aldığı aggregation bölümünün de dahil olmasını istiyoruz. Şöyle ki;

Sorguyu çalıştırdığımız zaman 4 kaydın başarıyla döndüğünü görebiliyoruz ancak aggregation’da bir sorun var gibi:

"aggregations": {
"categories": {
"doc_count_error_upper_bound": 0,
"sum_other_doc_count": 0,
"buckets": [
{
"key": 3,
"doc_count": 4
}
]
}
}

Diğer kategorilere ait doküman sayısını alamıyoruz. Tabii ki bu bir sorun değil. Çünkü Elasticsearch’e gönderilen REST isteğindeki query alanı, aggs alanından önce işleme sokulacak; sorgudan gelen sonuç setindeki kayıtlar bir aggregation işlemine dahil edilecektir.

Sanıyorum sorunu okurken yapılması gereken işlem kafamızda canlandı:

Filtreleme işleminin en son işlem olarak gerçekleştirilmesi

Yani Post filter. Dolayısıyla sorgudaki filtre alanı devre dışı kalmalı. Aggregation tüm kayıtlar üzerinde gerçekleşmeli, sonrasında sonuç setine filtre uygulanmalıdır. O halde sorgumuzu şu şekilde düzenleyerek deneyelim:

Artık bir query operasyonumuz yok. İlk olarak aggs operasyonu tamamlanacak; sonrasında ise sonuç setine bir filtre uygulanacak (post_filter). Son kullanıcıya dönen sonuç setinde göreceğimiz üzere ilk sorgu ile aynı kayıtlar mevcut (4 kayıt). Bununla birlikte aggregation alanı tam istediğimiz kıvama geldi diyebiliriz:

"aggregations": {
"categories": {
"doc_count_error_upper_bound": 0,
"sum_other_doc_count": 0,
"buckets": [
{
"key": 3,
"doc_count": 4
},
{
"key": 1,
"doc_count": 3
},
{
"key": 2,
"doc_count": 1
}
]
}
}

Sonuç

Bu işlemi ihtiyaçlar doğrultusunda genişletmek, query’ye filter geçtikten sonra post_filter işlemi uygulamak, farklı aggregation’lar için farklı filtreler uygulamak gibi yöntemler tabii ki işin ihtiyacına kalıyor.

Daha önceki Elasticsearch yazılarımda repo paylaşmadığım için özelden sitem eden dostlara özür mahiyetinde aşağıdaki repo adresini paylaşıyorum. Repodaki uygulama ASP.NET Core MVC uygulaması üzerinde NEST kütüphanesi ile aynı işi gerçekleştiriyor.

Son olarak; 2018'in herkese, hayallerine birden fazla adımla daha fazla yaklaştığı bir yıl olmasını temenni ediyorum. Mutluluk ve saygı da yeni yılda bir öncekinden daha fazla ihtiyaç duyduğumuz iki temel manevi değer.

Bir sonraki yazıda görüşene dek, filtrelerinizden hep “en az 1” kayıt dönmesi dileğiyle :)