Elasticsearch: Güçlü Veri Sorgulama Teknikleri [4/5]

Elasticsearch: Powerful Data Querying Techniques [4/5]

Cihat Solak
Intertech
8 min readDec 26, 2023

--

Term-level queri̇es, Full-text queri̇es ve Compound and aggregation queries, bilgi erişiminde temel kavramlardır. Term-level queri̇es belirli terimlerle ilgili aramalarda, full-text queri̇es geniş kapsamlı araştırmalarda etkilidir. Compound and aggregation ise farklı sorgu tiplerini birleştirerek özelleştirilmiş sonuçlar sağlar. Bu konular, bilgi yönetimi ve erişiminde stratejiler sunar. Bu makalede, temel sorgu türlerinin önemi ve kullanım alanlarına odaklanarak, etkili araştırma yöntemlerini ele alacağız.

Elasticsearch, belge tabanlı bir veri tabanıdır ve verilerin depolanması, indekslenmesi ve aranması için kullanılır.

1- Term-Level Queries

Yapılandırılmış verilerdeki (tarih aralıkları, IP adresleri, fiyatlar veya ürün id (kimlik) kesin değerleri temel alan belgeleri bulmak için terim düzeyinde sorguları kullanılabilir. Full-text search’den farklı olarak term-level sorgular, arama terimlerini analiz etmez. Bunun yerine terim düzeyindeki sorgular, bir alanda depolanan terimlerle tam olarak eşleşir.

Term-level sorgularda structured veriler üzerinde (kesin değerler) iki tarih arası veya id’ye göre arama şeklinde direkt arama yapılabilmektedir. İlişki değeri olmadığı için burada skor değeri bulunmamaktadır. Örneğin ‘Istanbul’da oturan kullanıcıları getir’ cityNumber == 34 dediğimizde tam olarak eşleşen kullanıcıları getirecektir.

Term-level query türünde analiz süreci (tokenization ve normalization) yoktur fakat full-text query türünde analiz süreci vardır.

Term-level query büyük/küçük harf duyarlılığına (case sensitive) sahiptir. Denizbank olarak kaydedilmiş veriyi denizbank olarak küçük harf ile aranırsa sonuç alınamaz.

1.1 — Term Query

Belirtilen alandaki tam eşleşmeyi kontrol eder. Fiyat, ürün id veya kullanıcı adı gibi kesin bir değere dayalı olarak belgeleri bulmak için terim sorgusu kullanılabilir.

{
"query": {
"term": {
"company_name.keyword": {
"value": "Intertech",
"case_insensitive": true
}
}
}
}

company_name.keyword sonunda keyword ifadesi yer almaktadır. Çünkü company_name alanına text ve keyword olmak üzere 2 adet tip ataması gerçekleştirilmiştir. Yukarıdaki sorguda keyword tipi üzerinden arama yapılmak istenildiği için keyword ile beraber belirtilmektedir.

Parametre isminin sonunda yer alan keyword aslında takma isim olup herhangi bir kelime (key, test, cihat, denizbank vb.) olabilir. Ancak best practices açısından isimlendirmeler önemlidir.

1.2 — Terms Query

Belirli bir alanda birden çok terimi eşleştirmek için kullanılan bir sorgu türüdür. Örneğin şirket adı Intertech veya Denizbank olanları listelemek gibi birden farklı değer ile arama yapılmak istenildiğinde kullanılabilir.

{
"query": {
"terms": {
"company_name.keyword": ["Intertech", "Denizbank"]
}
}
}

Yukarıdaki sorgu, belirtilen alandaki değerler arasında herhangi bir terimin bulunduğu belgeleri getirecektir.

1.3 — IDs Query

Belirli bir belge kimliği veya bir dizi belge kimliği üzerinde sorgulama yapmak için kullanılan bir sorgu türüdür. Bu sorgu, belirtilen belge kimlikleri ile eşleşen belgeleri getirir.

{
"query": {
"ids": {
"values": [
"gilUkYsBtQJw_l-qgx_s",
"qylUkYsBtQJw_l-qgx_t"
]
}
}
}

Bu sorgulama türü ID değerine göre kurgulanmış özel arama türüdür. Kaydedilen belgelerin ID değerine göre arama yapılabilir.

1.4 — Exist Query

Belirli bir alanın var olup olmadığını kontrol etmek için kullanılan bir sorgu türüdür. Bu sorgu, belirtilen bir alanın değerine bakmaksızın, yalnızca belgenin bu alanı içerip içermediğini kontrol eder.

Örneğin bank_name alanının var olup olmadığını kontrol eder. Çünkü NoSQL veri tabanlarında satırlar arasındaki field sayısının eşit olmasına gerek yoktur. Bir satırda 5 field, başka bir satırda 7 field olabilir. Dolayısıyla field var mı? yok mu? kontrolü yapılabilir.

{
"query": {
"exists": {
"field": "bank_name"
}
}
}

1.5 — Prefix Query (StartWith)

Belirli bir alanın değerine sahip belgeleri bulmak için bir önek (başlangıç) terimi kullanarak sorgu yapma yöntemidir. Bu sorgu, belirtilen alanın belirli bir önek ile başlayan değerlere sahip belgeleri getirir.

Tam bir değer üzerinden sorgulama yapmayıp, belirli karakterler ile başlayan verileri getirir. Örneğin aşağıdaki sorguda deniz ile başlayan banka isimlerini listeleyecektir.

{
"query": {
"prefix": {
"bank_name.keyword": {
"value": "deniz",
"case_insensitive": true
}
}
}
}

1.6 — Range Query

Belirli bir aralıktaki değerlere sahip belgeleri bulmak için kullanılan bir sorgu türüdür. Bu sorgu, belirtilen bir alanın değeri belirli bir aralıkta olan belgeleri filtrelemek için kullanılır.

Tipi keyword ya da text olan fieldlarda böyle bir kullanım sergileyemezsiniz.

{
"query": {
"range": {
"taxless_total_price": {
"gte": 20.50,
"lte": 40.00
}
}
}
}

1.7 — WildCard Query

Belirli bir desene uyan terimlere sahip belgeleri bulmak için kullanılan bir sorgu türüdür. Wildcard, belirli bir deseni ifade etmek için joker karakterleri (genellikle * veya ?) kullanır.

Prefix sorgusunda belirlenen karakterle başlayan (startwith) sonuçları listelerken, Wildcard sorgusu ise herhangi bir konumda bulunan belirli karakterlerle ilgili esnek bir arama yapmamıza olanak tanır.

Asterisk (*) : Birden fazla karakter

? : Tek karakter

{
"query": {
"wildcard": {
"bank_name.keyword": {
"value": "Deni*",
"case_insensitive": true
}
}
}
}

1.8 — Fuzzy Query

Benzer ancak tam olarak eşleşmeyen terimleri bulmak için kullanılan bir sorgu türüdür. Bu sorgu, belirli bir terimdeki karakter değişikliklerine veya yazım hatalarına karşı toleranslıdır. Böylece benzer terimlere eşleşen belgeleri bulmanıza yardımcı olur.

Kullanıcı arama yaparken harf hatası yaptığında bu harf hatasını elasticsearch tolere ediyor. Normalde wildcard aramasında * (yıldız) dersek birden fazla karakteri, (? soru işareti) dersek 1 adet karakteri temsil ediyor. * karakterini dinamik yapmak istediğimizde fuzzy sorgularına ihtiyaç duyuyoruz.

{
"query": {
"fuzzy": {
"bank_name.keyword": {
"value": "enizbank", //Denizbank
"fuzziness": 1
}
}
}
}

Örneğin kullanıcı Denizbank aramasında baştaki D harfini unuttu. Search işleminde fuzziness değerini 1 (bir) belirleyerek başında herhangi bir harf olabileceğini vurgular ve uygun olan verileri listeleyebiliriz.

Örneğin bal araması için (fuzziness: 1) kullanıcıya kal, çal, dal, şal, nal gibi kelimeleri listelenir. Yani tek bir harf hatasına karşılık sonuçları getiriyor.

Fuzziness değeri belirlenmezse elasticsearch aranan kelimenin uzunluğuna göre otomatik fuzziness değeri belirler. Örneğin 5 karakterden fazla ise fuzziness değerini 2 olarak belirliyor.

Harf hatasının başta ya da sonda olması zorunda değildir, kelime ortasında da hata olabilir.

1.9 — Pagination Query

Tüm sorgular türlerinde (full-text search/term level query) kullanılabilir.

{
"from": 1,
"size": 5,
"query": {
"fuzzy": {
"customer_first_name.keyword": {
"value": "Stephanie",
"fuzziness": 0
}
}
}
}

1.10— Response Includes/Excludes (Select)

Herhangi bir arama yapıldığında veri tabanındaki tüm fieldlar listelenir. Ancak arama sırasında, source keyword’ü içerisinde include ve exclude yöntemiyle response’da sadece ihtiyaç olacak field’lar belirlenebilir.

{
"_source": {
"includes": [
"category",
"customer_first_name"
],
"excludes": [
"currency"
]
},
"from": 1,
"size": 5,
"query": {
"fuzzy": {
"customer_first_name.keyword": {
"value": "Stephanie",
"fuzziness": 0
}
}
}
}

1.11 — Sort Query (OrderBy)

Full-text search işleminde sıralama yapmak score değerine göre sıralanmış veriyi bozacağı için uygun değildir. Mümkün olduğunca sadece term-level sorgularda kullanılmalıdır. Çünkü full-text search işleminde dönen response sıralaması aranan kelime ile alaka düzeyine (score) göre sıralanmaktadır. Bunun üstüne ekstra bir sıralama yapmak uygun değildir.

{
"query": {
"term": {
"customer_gender": {
"value": "MaLE",
"case_insensitive": true
}
}
},
"sort": [
{
"taxless_total_price": {
"order": "desc"
},
"customer_first_name.keyword": {
"order": "asc"
}
}
]
}

Full-Text Queries

Elasticsearch, büyük veri setleri üzerinde (blog içerikleri, haber bildirimleri, word dosyaları vb.) etkili bir arama yapma imkanı sunan güçlü bir veri tabanıdır.

1.1 — Match Query

Belirli bir alan içinde belirli bir terimi aramak için kullanılan temel bir sorgu türüdür. Bu sorgu, belirtilen alan içindeki belgeleri belirli bir terim veya ifadeyle eşleştirmek için kullanılır.

Full-text search işlemi denildiğinde akıllara ilk gelecek kelime match olmalıdır.

{
"query": {
"match": {
"personal_full_name": "Cihat Solak"
}
}
}

//Operator belirtilmediği sürece OR anlamında sorgular. Cihat ya da Solak

Full-text işlemini makale başlık ve içeriklerinde veya haber içeriği/başlığı gibi hacimli veriler üzerinde kullanılmalıdır. Başlık gibi fieldlarda tip belirlenirken hem keyword hemde text olarak belirlemekte fayda vardır.

{
"query": {
"match": {
"personal_full_name": {
"query": "Cihat Solak",
"operator": "and"
}
}
}
}

Asıl olarak full-text arama avantajından yararlandığımız alanlar, “text” türünde olanlardır.

{
"query": {
"match": {
"personal_full_name": {
"query": "Cihat Solak",
"operator": "and",
"fuzziness": 2
}
}
}
}

Yukarıdaki sorgu gövdesini incelediğimizde

  • Fuzziness ile 2 harf hatasının kabul edildiğini
  • And operatörü ile Cihat Solak ifadesini birlikte ara, her ikisinin bulunduğunu nesneleri getir. Yani Cihat Aran isminde Cihatgeçiyor diye getirme.
  • Fuzziness değeri ne kadar yüksek belirlenirse, o derece ilgisiz veri listelenir. Dolayısıyla fuzziness değerini auto olarak ayarlamak iyidir.

Fuzziness değerini auto olarak belirlemek best practices açısından önem arz etmektedir.

Company Name: Intertech Information Technology and Marketing Inc.

// 1. Sorgu
{
"query": {
"match": {
"bank_name": "Intertech Information Technology and Marketing Inc."
}
}
}

// 2. Sorgu
{
"query": {
"match": {
"bank_name": "Technology and Marketing Inc."
}
}
}

// 3. Sorgu
{
"query": {
"match": {
"bank_name": "Marketing"
}
}
}

Yukarıdaki örneği incelediğimizde tüm sorgulamalarda Intertech Information Technology and Marketing Inc. şirketi response’da yer alacak ancak skor değerinde farklılıklar yaşanacaktır.

Doktorlar Reçeteleri Neden Anlaşılmaz Bir Şekilde Yazarlar? başlığında bir match araması yaparken Reçete diye arama gerçekleştirdiğimizde sonuç alamayız. Reçeteleri şeklinde tam eşleşecek şekilde arama yapılmalıdır.

1.2 — Multi Match Query

Birden çok alanı aynı anda sorgulamak için kullanılan bir sorgu türüdür. Bu, belirli bir terimi veya ifadeyi birden çok alan içinde aramak için kullanışlıdır. Özellikle bir kullanıcının arama terimini birkaç farklı alan içinde eşleştirmek istediğinizde kullanılır.

{
"query": {
"multi_match": {
"query": "DenizBank",
"fields": [ "company_name", "address", "edge_plate", "title" ],
"operator": "or",
"fuzziness": "auto",
"type": "best_fields" //most_fields, cross_fields, phrase_prefix
}
}
}

1.3 — Match Bool Prefix Query

Aranılan metinde en sonda yer alan kelimeyi prefix olarak algılamaktadır. Sondaki kelime prefix ardından varsa diğer kelimeler OR koşuluyla aranmaktadır. Prefix olarak belirlenen kelime hariç, diğer kelimelerde tam eşleşme beklemektedir.

Cihat Mesut So ismindeki kullanıcıyı “Cihat Mesut So...” olarak aradığını düşünebiliriz. Cihat geçenler OR Mesut Geçenler OR So… geçenler. So’dan sonra ne olursa…

{
"query": {
"match_bool_prefix": {
"personal_full_name": "Cihat Mesut So"
}
}
}

Formül: So… OR Mesut OR Cihat

Çıkan sonuçlarda SoLAKOĞLU olabilir ama So ile başlaması gereklidir. Arkasından Cihat arkasından Mesut olabilir. So ile başlayacak geri kalanı OR şeklinde devam edecek.

1.4 — Match Phrase Query

Öbek kelimeleri aramak için kullanılır. Örneğin Cihat Solak diye aradığınızda klasik match sorgusunda Cihat veya Solak geçenleri arar. Match Phrase olduğunda Cihat Solak geçenleri getirir ve sırası da önemlidir. İlk kelime cihat sonraki kelime solak olmak zorundadır.

{
"query": {
"match_phrase": {
"personal_full_name": "Cihat Solak"
}
}
}

Normalde şartlarda aramada “Cihat Solak” kelimesinin sıralamasının bir önemi yoktur. Yani “Cihat” kelimesi full name’in herhangi bir yerinde geçebilir. Eğer ki ben sıralı bir şekilde arama yapmak isteniliyorsa, birinci kelime “Cihat” ikinci kelime “Solak” olacak şekilde sırasının bir önemi varsa işte burada phrase query devreye giriyor. Yani bir cümleyi tam bir sıralama içerisinde arıyor.

match aramasında kelimelerin sıralaması önemli değildir ancak match_phrase sorgulamasında kelimeler tam sıraları olmalıdır. “Solak Cihat” kaydını bulamazdı çünkü sıralı sisteme uymuyor.

1.5 — Match Phrase Prefix Query

Aranılan kelimede en sonda yer alan kelimeyi prefix olarak algılamaktadır. Aranacak kelime ya da kelimelerin sıralaması önemlidir.

{
"query": {
"match_phrase_prefix": {
"personal_full_name": "Mehmet Yılmaz Arm"
}
}
}

Yukarıdaki aramanın sonucu aşağıdaki şekilde olabilir.

  • Mehmet Yılmaz Armağan
  • Mehmet Yılmaz Arm
  • Ömer Mehmet Yılmaz Armay

--

--