9 puan yazan GN⁺ 2025-11-18 | 1 yorum | WhatsApp'ta paylaş
  • Mevcut veritabanını kullanarak harici servis olmadan çalışan bir arama motoru mimarisi kuruyor; odak noktası tokenization, ağırlıklandırma ve skorlamadır
  • Temel fikir, tüm metni token’lara ayırıp saklamak ve arama sırasında aynı yöntemle token’ları eşleştirerek ilgililiği hesaplamaktır
  • Word, Prefix, N-Gram tokenizer kombinasyonu ile tam eşleşme, kısmi eşleşme ve yazım hatası toleransı birlikte ele alınır; her tokenizer’ın kendine özgü bir ağırlığı vardır
  • Ağırlık sistemi ve SQL tabanlı skorlama algoritması ile belge uzunluğu, token çeşitliliği ve ortalama kalite birlikte değerlendirilir
  • Ölçeklenebilirlik ve şeffaflık yüksektir; yeni tokenizer ya da belge türü eklemek, ağırlıkları ayarlamak ve skorlama mantığını değiştirmek serbesttir

Neden kendi arama motorunu yapmak gerekir?

  • Elasticsearch veya Algolia gibi harici servisler güçlüdür, ancak karmaşık API’leri öğrenme ve altyapı yönetimi yükü getirir
  • Sadece mevcut veritabanıyla entegre çalışan ve hata ayıklaması kolay bir arama özelliği gerektiğinde, bunu doğrudan inşa etmek faydalıdır
  • Amaç, harici bağımlılık olmadan yüksek ilgililikte sonuçlar döndüren basit bir arama motoru oluşturmaktır

Temel kavram: tokenization ve eşleştirme

  • Temel ilke, tüm metni tokenize edip saklamak ve arama sırasında aynı şekilde token üretip eşleştirmektir
  • İndeksleme aşamasında içerik token düzeyinde ayrılır ve ağırlıklarıyla birlikte saklanır
  • Arama aşamasında sorgu da aynı şekilde tokenize edilir, eşleşen token’lar bulunur ve puan hesaplanır
  • Skorlama aşamasında saklanan ağırlıklar kullanılarak ilgililik skoru üretilir

Veritabanı şeması tasarımı

  • İki tablo kullanılır: index_tokens ve index_entries
    • index_tokens: benzersiz token’ları ve tokenizer bazlı ağırlıkları saklar
    • index_entries: token’ları belgelerle ilişkilendirir ve alan, belge ve tokenizer ağırlıklarını yansıtan son skoru saklar
  • Nihai ağırlık hesaplama formülü:
    field_weight × tokenizer_weight × ceil(sqrt(token_length))
  • İndeksler; belge sorgulama, token sorgulama, alan bazlı sorgular ve ağırlık filtreleme için tanımlanır

Tokenization sistemi

  • WordTokenizer: kelime bazlı ayırma, kısa kelimeleri kaldırma, tam eşleşme için (ağırlık 20)
  • PrefixTokenizer: kelime önekleri üretir, otomatik tamamlama ve kısmi eşleşme için (ağırlık 5)
  • NGramsTokenizer: sabit uzunluklu karakter kombinasyonları üretir, yazım hataları ve kısmi eşleşmeler için (ağırlık 1)
  • Tüm tokenizer’lar ortak olarak küçük harfe çevirme, özel karakterleri temizleme ve boşlukları normalize etme işlemlerini yapar

Ağırlık sistemi

  • Alan ağırlığı: başlık, gövde, anahtar kelime gibi alanların önemini yansıtır
  • Tokenizer ağırlığı: Word > Prefix > N-Gram sırasındadır
  • Belge ağırlığı: bu iki unsur ile token uzunluğunun birleşiminden hesaplanır
  • ceil(sqrt()) fonksiyonu, uzun token’ların etkisini yumuşatmak için kullanılır; gerekirse logaritmik ya da doğrusal fonksiyonlarla ayarlanabilir

İndeksleme servisi

  • Yalnızca IndexableDocumentInterface uygulayan belgeler indekslenebilir
  • Belge oluşturma veya güncelleme sırasında event listener ya da komutlarla (app:index-document, app:reindex-documents) indeksleme yapılır
  • Süreç:
    • Eski indeks kaldırılır, ardından yeni token’lar üretilir
    • Her alan için tüm tokenizer’lar çalıştırılır
    • Token’ın var olup olmadığı kontrol edilir ve gerekirse oluşturulur (findOrCreateToken)
    • Hesaplanan ağırlıklarla index_entries tablosuna toplu ekleme (batch insert) yapılır
  • Yapı; tekrarları önleme, performansı artırma ve güncellemeleri karşılama amacı taşır

Arama servisi

  • Sorgu, aynı tokenizer’larla işlenerek indekslemeyle aynı token kümesi elde edilir
  • Tekrarlanan token’lar kaldırılır, uzunluğa göre sıralanır (uzun token önce gelir) ve en fazla 300 token ile sınırlandırılır
  • SQL sorgusu üzerinden token ve belge join edilerek ilgililik skoru hesaplanır ve sıralama yapılır
  • Sonuçlar SearchResult(documentId, score) biçiminde döner

Skorlama algoritması

  • Temel skor: SUM(sd.weight)
  • Token çeşitliliği düzeltmesi: LOG(1 + COUNT(DISTINCT token_id))
  • Ortalama ağırlık düzeltmesi: LOG(1 + AVG(weight))
  • Belge uzunluğu cezası: 1 / (1 + LOG(1 + token_count))
  • Normalizasyon: en yüksek skora bölünerek 0~1 aralığına getirilir
  • Minimum token ağırlığı filtresi (st2.weight >= ?) ile anlamsız, düşük ağırlıklı eşleşmeler elenir

Sonuç işleme

  • Arama sonuçları belge ID’si ve skor olarak döner; repository üzerinden gerçek belgelere dönüştürülür
  • FIELD() fonksiyonu kullanılarak arama sonucu sırası korunarak belge sorgulaması yapılır

Sistemin genişletilebilirliği

  • Yeni tokenizer’lar TokenizerInterface uygulanarak eklenebilir
  • Yeni belge türleri IndexableDocumentInterface uygulanarak kaydedilebilir
  • Ağırlıklar veya skorlama mantığı yalnızca SQL değiştirilerek ayarlanabilir

Sonuç

  • Bu yapı, basit ama gerçekten çalışan bir arama motorudur ve harici altyapı olmadan da yeterli performans sunar
  • Açık mantık, tam kontrol ve kolay hata ayıklama en büyük avantajlarıdır
  • Karmaşık sistemlerden ziyade doğrudan anlayıp kontrol edebileceğiniz kodun daha değerli olduğunu vurgular

1 yorum

 
GN⁺ 2025-11-18
Hacker News görüşleri
  • Aramanın temel fikri basit ve ilgi çekici bir problem alanı.
    Ama büyük miktarda veriyle uğraşmak ve belirsiz sorguları işlemek asıl zor kısım.
    DBMS tabanlı yaklaşım küçük web siteleri düzeyinde idare eder, ancak İngilizce Vikipedi ölçeğinde hızla sınırlarına dayanır.
    Başlangıç için SeIRP e-book iyi bir ücretsiz kaynak.

    • Büyük veri doğal olarak zordur, ama belirsiz sorgularla uğraşmanın “en alakalı sonucun nasıl belirleneceği” sorununun bir alt problemi olduğunu düşünüyorum.
      Net bir doğru cevabın olmaması bunu özellikle zorlaştırıyor.
      Google bazen reklamları da ‘en alakalı sonuç’ olarak gösteriyor; bu yüzden Marginalia Search iyi bir karşıt örnek.
      Acaba hiç TREC makalelerine baktınız mı diye merak ettim.
    • Bugünlerde asıl daha büyük sorunun SEO spam’inden kaçınmak olduğunu düşünüyorum.
      Arama motorları, reklam geliri peşindeki hasım aktörlerle sürekli mücadele etmek zorunda.
      Kalite metriklerini sürekli değiştirip onların bunu istismar edememesini sağlamak, bitmeyen bir kedi-fare oyununa dönüşüyor.
    • SQLite ile tek bir sunucuda (yaklaşık bin dolar seviyesinde) metin ağırlıklı iş süreçleri çalıştırılacaksa, pratikte yönetilebilecek belge deposu ölçeğinin ne kadar olacağını merak ediyorum.
      Sorgu başına 5 saniye ve dakikada 12 sorgu civarı bir hızla ne büyüklükte bir korpusta arama yapılabileceğini bilmek isterdim.
    • Marginalia Search’ü gerçekten çok seviyorum.
    • Aramanın zorluğu yalnızca veri boyutu değil, hangi sonucun döndürüleceğine karar verme meselesi de.
      Örneğin Gilligan’s Island wiki sayfası ile bir hayran blogu arasında hangisinin daha “iyi” sonuç olduğunu belirlemek zor.
      Buna bir de sıralama manipülasyonu veya anahtar kelime doldurma eklenince, bu sorun ölçeklenebilirlikten çok daha karmaşık bir meydan okumaya dönüşüyor.
  • Arama gerçekten çok zor bir iş.
    Apple, Microsoft, OpenAI gibi kaynak ve teknik güç açısından çok güçlü şirketlerin bile arama kalitesi düşük.
    Bu sadece teknik bir sorun değil.

    • Çoğu şirketin aramayı iyi uygulayamamasının nedeni, kurum kültürü ve geliştirme biçiminin arama geliştirmeyle çatışması.
      Arama kalitesini artırmak için sıralama parametrelerini ince ayarlamak gerekiyor, ama böyle işler sprint veya Jira benzeri yönetim çerçeveleriyle planlanması zor şeyler.
      Sonuçta bu alan geliştiriciye güven ve özerklik gerektiriyor.
    • Ama bazı şirketlerde kalite düşüklüğünün nedeni basitçe aramanın öncelik olmaması.
      Yapay zeka modellerine milyarlar yatırıyorlar, ama web uygulaması ya da arama ikincil kaldığı için sonuç böyle oluyor.
  • Yaklaşık 10 yıl önce arama motoru tasarımı üzerine doktora yapan bir meslektaşımla çalışma fırsatım olmuştu.
    Arama ile veritabanı entegrasyonu hakkında büyük bir tutkuyla konuşuyordu ve ondan çok şey öğrendim.
    Bir gün Apache Solr ve Lucene’in iç yapısını derinlemesine incelemek istiyorum.

    • Ben de kendi alanım hakkında saatlerce konuşabilecek kadar hevesliyim, ama büyük sistemlerin ayrıntılı uygulamasıyla ilgilenen insan sayısı çok değil.
  • Eskiden açık kaynak arama çözümleri yoktu, bu yüzden kendin yapmak zorundaydın.
    O deneyimden çıkan ders şu oldu: “Kendi arama motorunu yapma.”
    Yıllarca sayısız insan bu problem üzerinde çalıştı; kendin yaparsan bitmeyen bir bakım cehennemine giriyorsun.
    “Yazım düzeltme özelliği ekleyelim”, “seneye sınıflandırma da koyalım” gibi talepler gelmeye başlayınca sonu gelmiyor.

  • Bir zamanlar Virginia University’den Profesör David Evans’ın verdiği arama motoru geliştirme dersinden gerçekten çok keyif almıştım.
    “Klasik bir arama motorunu” doğrudan inşa etmek çok eğlenceli bir projeydi.
    Ders bağlantısı ve YouTube oynatma listesi incelenebilir.

    • Ben de o dersi almıştım; acemi programcılar için bile ilgi çekici ve yoğun bir dersti.
  • Sık kullandığım arama motorlarının 2-3 harfli kısaltmaları veya kelimeleri yok saymasına sinir oluyorum.
    “mp3” veya “PHP” gibi kısa sözcükleri ararken bunların atılması gerçekten çok can sıkıcı.

  • Toby Segaran’ın Programming Collective Intelligence kitabını okuyup arama, öneri sistemleri ve sınıflandırıcılar gibi çeşitli fikirlerden ilham almıştım.

    • Ben de o kitabı sevmiştim, ama yazarın daha sonra YouTube’da “artık demode, kullanmayın” dediğini görmüştüm.
    • Gerçekten çok iyi bir kitaptı; acaba 2025’e uygun güncel bir sürümü var mı diye merak ediyorum.
  • İlginç bir yazıydı.
    Popüler arama motorlarının kullandığı tokenizer optimizasyonunun seviyesi ne kadar yüksek, merak ettim.

  • Bu sistemin ne kadar ölçeklenebilir çalışacağını merak ediyorum.
    Elasticsearch, önerilen ölçeğin ötesinde bile oldukça etkileyici performans gösteriyor.

  • Basit bir metin arama motoru yapmak zor değildir.
    Ama iyi bir arama motoru yapmak tamamen başka bir mesele.
    Sadece BM25 gibi bir algoritmayı uygulamak yeterli değil.
    Danışmanlık verdiğim şirketlerin çoğu kendi çözümlerini kullanıyordu ama sonunda Elasticsearch veya Opensearch’e geçti.
    Kendi uygulaman ilk başta basit görünür, ama zamanla sıralama sorunları ve performans düşüşü yüzünden karmaşıklaşır.
    “Yavaş”, “saçma sonuçlar veriyor” gibi belirtiler tekrar tekrar ortaya çıkar.
    Elasticsearch bu tür sorunları zaten 10 yılı aşkın süredir çözüyor ve bugün çok daha ileri durumda.
    “Yapılandırması zor” deniyor ama artık çoğu şey otomatik yapılandırılıyor ve pek çok yönetilen hizmet de var.
    Postgres’ten bile daha kolay yönetilebilir.
    Sonuçta önemli olan indeks eşleme optimizasyonu.
    “Böyle gelişmiş özelliklere gerek yok” diyenler oluyor, ama gerçekte arama kalitesi işletmenin hayatta kalmasıyla doğrudan bağlantılı.
    Düzgün bir arama istiyorsan sonunda bu karmaşıklığı kabullenmek zorundasın.

    • Ben de varsayılan olarak Elasticsearch kullanıyorum.
      Son dönemde HN’de sık anılan SeekStorm gibi yükselen alternatifler de ilginç görünüyor, ama henüz gerçek üretim örneklerini görmedim.
    • “Gereksiz özellik yoktur” sözüne katılıyorum.
      Özellikle dynamic mapping’i kapatıp gereksiz alanların indekslenmesini engelleme ipucu faydalıydı.
    • ManticoreSearch hakkında ne düşündüğünüzü merak ediyorum.
      Bildiğim kadarıyla Lucene’den daha eski bir proje.