Bu makalede Fuzzy Query’den bahsedeceğim. Örneklerimizi Docker Desktop ‘a kuracağımız elasticsearch ve kibana konteynerleri üzerinde gerçekleştireceğiz. Bu şekilde daha hızlı uygulanabilir örnekler elde edebileceğimizi düşünüyorum. Ek olarak bonus bir framework ten de bahsedeceğim. Özetle akış şu şekilde olacak :
- Fuzzy Query Nedir?
- Docker Desktop ‘a Elasticsearch ve Kibana Kurulumu
- Kibana Console – Dev Tools
- Yeni Index Oluşturma
- Bulk Data Girişi
- Fuzzy Query Örneği
- Boosting Kullanımı
Fuzzy Query Nedir?
Fuzzy Query, arama sorgularında hatalı yazılmış, eksik, fazla karakter içeren veya benzer kelimeleri de eşleştirmek için kullanılan bir tekniktir. Kısaca “benzer eşleşme” yapar. Yani ilgili data içerisinde sorgulanan terim ile tam olarak eşleşmeyen ama benzer olan sonuçları da getirir. Bu işlem arka planda genellikle Levenshtein Distance (Levenshtein Mesafesi) algoritması kullanılarak gerçekleştirilir. Konuyla ilgili detayları incelemek isterseniz daha önce yazdığım “Levenshtein Mesafesi (Levenshtein Distance) Nedir?” blog yazısını inceleyebilirsiniz.
Docker Desktop ‘a Elasticsearch ve Kibana Kurulumu
Docker-compose.yml dosya içeriği aşağıdaki gibi. Dosyayı herhangi bir klasöre attıktan sonra docker-compose up komutu ile konteyner larını kurulmasını ve ayağa kalkmasını sağlayabilirsiniz.
version: '3.8'
services:
elasticsearch:
image: docker.elastic.co/elasticsearch/elasticsearch:8.7.1
expose:
- 9200
environment:
- xpack.security.enabled=false
- "discovery.type=single-node"
- ELASTIC_USERNAME=elastic
- ELASTIC_PASSWORD=DkIedPPSCb
networks:
- es-net
ports:
- 9200:9200
volumes:
- elasticsearch-data:/usr/share/elasticsearch/data
kibana:
image: docker.elastic.co/kibana/kibana:8.7.1
environment:
- ELASTICSEARCH_HOSTS=http://elasticsearch:9200
expose:
- 5601
networks:
- es-net
depends_on:
- elasticsearch
ports:
- 5601:5601
volumes:
- kibana-data:/usr/share/kibana/data
networks:
es-net:
driver: bridge
volumes:
elasticsearch-data:
driver: local
kibana-data:
driver: local
Kibana Console – Dev Tools
Kurulumu tamamladıysanız, Kibana Console Dev Tools arayüzüne http://localhost:5601/app/dev_tools#/console bu şekilde erişebiliyor olmalısınız. Öncelikle örnek verilerimizi tutacağımız products_st adında yeni bir index oluşturalım.
PUT /products_st
{
"mappings": {
"properties": {
"name": {
"type": "text"
},
"price": {
"type": "float"
}
}
}
}
Daha sonra index içerisine bulk olarak dummy data gönderelim. Sorgu sonucunda bulacağımız her sonuç score unun farklı olduğunu görebilmek için yazım hataları olan veya benzer kayıtları bilerek ekledim.
POST /products_st/_bulk
{ "index": { "_id": 1 } }
{ "name": "Ekran Kartı", "price": 8500.0 }
{ "index": { "_id": 2 } }
{ "name": "Anakart", "price": 3200.0 }
{ "index": { "_id": 3 } }
{ "name": "İşlemci", "price": 6700.0 }
{ "index": { "_id": 4 } }
{ "name": "RAM Bellek", "price": 1200.0 }
{ "index": { "_id": 5 } }
{ "name": "SSD Disk", "price": 2100.0 }
{ "index": { "_id": 6 } }
{ "name": "HDD Disk", "price": 950.0 }
{ "index": { "_id": 7 } }
{ "name": "Kasa", "price": 1800.0 }
{ "index": { "_id": 8 } }
{ "name": "Güç Kaynağı", "price": 1100.0 }
{ "index": { "_id": 9 } }
{ "name": "Monitör", "price": 4500.0 }
{ "index": { "_id": 10 } }
{ "name": "Klavye", "price": 650.0 }
{ "index": { "_id": 11 } }
{ "name": "Mouse", "price": 350.0 }
{ "index": { "_id": 12 } }
{ "name": "Kulaklık", "price": 800.0 }
{ "index": { "_id": 13 } }
{ "name": "Ekran Karı", "price": 8400.0 }
{ "index": { "_id": 14 } }
{ "name": "Ekran Kart", "price": 8300.0 }
{ "index": { "_id": 15 } }
{ "name": "Ekraan Kartı", "price": 8600.0 }
{ "index": { "_id": 16 } }
{ "name": "Ankart", "price": 3100.0 }
{ "index": { "_id": 17 } }
{ "name": "Ana Kart", "price": 3300.0 }
{ "index": { "_id": 18 } }
{ "name": "Ram Belleği", "price": 1250.0 }
{ "index": { "_id": 19 } }
{ "name": "Ram Belleg", "price": 1190.0 }
{ "index": { "_id": 20 } }
{ "name": "SsdDisc", "price": 2050.0 }
{ "index": { "_id": 21 } }
{ "name": "HDDDisc", "price": 940.0 }
{ "index": { "_id": 22 } }
{ "name": "Kasaa", "price": 1790.0 }
{ "index": { "_id": 23 } }
{ "name": "Guc Kaynagı", "price": 1120.0 }
{ "index": { "_id": 24 } }
{ "name": "Monotor", "price": 4400.0 }
{ "index": { "_id": 25 } }
{ "name": "Monitr", "price": 4550.0 }
Buraya kadar herşey tamamsa artık Fuzzy Query mizi Dev Tools üzerinde yazarak nasıl çıktı elde ettiğimizi görebiliriz. Öncelikle bütün kayıtları çekerek datamızın varlığını kontrol edelim.
GET products_st/_search
{
"size":50,
"query": {"match_all": {}}
}
Sorguyu çalıştırdığımızda 25 kaydın gelmesi gerekiyor. Burada “size” değerini vermezseniz default olarak 10 kayıt gelecektir.

Şimdi “ekran” kelimesini Fuzzy Query ile aratarak eşleşmeleri bulalım ve score larını inceleyelim.
GET /products_st/_search
{
"query": {
"bool": {
"must": {
"fuzzy": {
"name": {
"value": "ekran",
"fuzziness": "AUTO"
}
}
}
}
}
}

Yukarıda gördüğünüz gibi bulunan her sonuç için bir _score değeri üretiliyor. En yüksek score en iyi eşleşen sonuç anlamına geliyor. Sorgudaki “fuzziness”: “AUTO” değeri Fuzzy Query’nin ne kadar toleranslı olacağını otomatik olarak belirlememizi sağlıyor. Fakat sayısal bir değer verirsek : Örneğin değer olarak “2” verilirse, 2 karakter farkı tolere eder.
Alan bazında boosting vererek ağırlığa göre arama yapmak isterseniz, her alan için boost tanımlayabilir, boosting sayesinde her alana bir ağırlık katsayısı (boost) verebilirsiniz. Böylece daha yüksek boost alan, daha yüksek _score üretir ve daha üst sıralara çıkar.
GET /products_st/_search
{
"query": {
"fuzzy": {
"name": {
"value": "kart",
"fuzziness": "AUTO",
"boost": 3.0
}
}
}
}
Birden fazla alan için tanımlama yapmak isterseniz, multi_match kullanabilirsiniz. Index imizde “description” adında yeni bir alanın daha olduğunu varsayarsak:
GET /products_st/_search
{
"query": {
"multi_match": {
"query": "kart",
"fields": [
"name^2",
"description^1"
],
"fuzziness": "AUTO"
}
}
}
“name” için 2, “description” için 1 olarak ağırlık verebilir ve bu ağırlıklara göre _score ların üretilmesi sağlanabilir.
Bu konu ile ilgili .Net üzerinde örnekte yapmak istiyorum ama makaleyi daha fazla uzatmamak için burada bitiriyorum. .Net için örnek yapmak isterseniz Elastic.Clients.Elasticsearch paketini kullanabilirsiniz (Github: https://github.com/elastic/elasticsearch-net). Elasticsearch ten bağımsız projenizde Fuzzy Query kullanmak isterseniz, yine aynı algoritmayı kullanan FuzzySharp ‘ı (https://github.com/JakeBayer/FuzzySharp) tercih edebilirsiniz.
Başka bir makalede görüşmek üzere.