Elasticsearch — Arama Sonuçlarını Gruplama (DISTINCT)

Alihan Koç
3 min readOct 3, 2020

--

Merhaba değerli okuyucu. Bu yazıda konumuz Elasticsearch.
Elasticsearch kullanırken arama yaptığımız zaman gelen sonuçlarda aynı olan kayıtların sonuçlarda sadece bir kez listelenmesini isteyebiliriz. Bu yazımızda bunu nasıl yapacağımızdan bahsedeceğiz. 😃

Ben örnekler üzerinden anlatmayı seviyorum. Bu yüzden bir örnek seçtim kendime. Örneğimiz aşağıda. 💥

Farz edelim ki bir araç kiralama uygulamamız var. Belirli tarihler arasında müsait olan araçları listeliyoruz. Fakat araç kiralama şirketimizde aynı model araçlardan 10 ar tane var. Örneğin 10 tane Hyundai i20, 10 tane Hyundai i30, 10 tane de Renault Clio var. Yine farz edelim ki arama yaptığımız zaman istediğimiz tarihlerde 5 tane i20, 3 tane i30, 8 tane de Clio müsait olsun.
🚗 🚙 🚓

Arama sonucunda biz 16 tane araç mı listelemeliyiz yoksa 3 tane mi? Cevap 3 olacak. Her modelden 1 tane listeleyeceğiz. Çünkü listeleme yaparken kaç tane aracımızın müsait olduğu son kullanıcıyı ilgilendirmez. Her bir araçtan bir tane göstermemiz gerekir. 🥉

Bu yüzden aynı model araçları gruplayarak hepsini 1 kere göstermemiz gerekiyor. Bunu yapabilmek için Elasticsearch’te collapse özelliğini kullanıyoruz. Bu şekilde sonuçlarımızda istediğimiz anahtara göre gruplama yapabiliyoruz.

Şimdi vehicles adında bir index oluşturalım. Mapping’ini yapalım.

Collapse yapabilmemiz için mapping yaparken gruplama yapacağımız key’in keyword tipinde map edilmiş olması gerekiyor.

PUT /vehicles
{
"mappings": {
"properties": {
"brand": { "type": "text" },
"model": { "type": "text" },
"group_key": { "type": "keyword"}
}
}
}

Group key de neyin nesi? Gruplama yaparken benzersiz bir alana göre gruplama yapmamız lazım. Mesela marka ya göre gruplama yapacak olursak her markadan sadece bir tane araç gelir tüm modeller listelenmez. Modele göre gruplayabiliriz.

Ancak aynı model isminden ya başka bir markada da varsa? Benim senaryomda olmayabilir ama sizde olabilir. Bu yüzden benzersiz bir alan oluşturmamız lazım. Mesela benim örneğimde group_key için hyundai-i20, renault-clio gibi değerlerle aracın modelini benzersiz bir şekilde gruplayabilirim. 👏

O zaman indeximize değerler ekleyerek devam edelim.

# her kayıttan 5 tane ekleyelimPOST vehicles/_doc
{
"brand":"Hyundai",
"model":"i30",
"group_key": "hyundai-i30"
}
POST vehicles/_doc
{
"brand":"Hyundai",
"model":"i20",
"group_key": "hyundai-i20"
}
POST vehicles/_doc
{
"brand":"Renault",
"model":"Clio",
"group_key": "renault-clio"
}

Bu şekilde hiç bir ek sorgu yapmadan arama yapıp sonuçları görelim.

GET vehicles/_search

Sonuç aşağıdaki gibi.

Gördüğünüz gibi tüm araçlarımız müsait olduğu için 15 tane sonuç geldi. Hyundai i20'lerin birden fazla olduğu görünüyor görselde. Oysa biz her modelden 1 tane gelecek şekilde 3 tane sonuç gelmesini beklemeliyiz. O zaman sorgumuzu aşağıdaki şekilde düzenleyelim.

GET vehicles/_search
{
"collapse": {
"field": "group_key"
}
}

Sorgumuzda group_key’e göre gruplamasını istediğimizi belirttik. Bu sorguyu çalıştırdığımız zaman elde edeceğimiz sonuç ise aşağıdaki gibi. 🍉

Gördüğümüz gibi sonuçlarımızda sadece 3 tane araç var. SQL’deki karşılığı DISTINCT olan sorguyu Elasticsearch’te bu şekilde yapıyoruz. Collapse özelliği altında başka özellikler de barındırıyor. Inner hits kullanarak hangi araç türünden aslında kaç tane var ve biz kaç tanesini gösterdik gibi sonuçları alabiliriz. Detaylı inceleme için link bırakıyorum.

❓Sorularınızı hello@alihankoc.com.tr eposta adresimden iletebilirsiniz.

Başka bir yazıda görüşmek üzere.
Sevgilerle. ✋

--

--