Custom Analyzer Oluşturma — Synonym, Autocomplete
Giriş — Terzi İşi Çözüm
Hazır takım elbiseler çoğu insan için yeterlidir, ama profesyonel bir sanatçının sahneye çıkacağı kıyafet özel dikilmelidir. Her dikiş, her ölçü, o kişiye özel olmalıdır. Elasticsearch'te de built-in analyzer'lar çoğu senaryo için işe yarar; ancak Türkçe e-ticaret araması, autocomplete, eşanlamlı destekli arama gibi özel ihtiyaçlar için custom analyzer oluşturmanız gerekir.
Bu derste, sıfırdan custom analyzer tasarlamayı öğreneceğiz. Türkçe arama optimizasyonu, synonym desteği ve autocomplete (search-as-you-type) gibi gerçek dünya senaryolarını adım adım inşa edeceğiz.
1. Custom Analyzer Anatomisi
Bir custom analyzer, üç bileşenin birleşiminden oluşur:
{
"type": "custom",
"char_filter": [...], // 0 veya daha fazla
"tokenizer": "...", // tam olarak 1
"filter": [...] // 0 veya daha fazla
}Custom analyzer'lar, index settings altındaki analysis bölümünde tanımlanır:
PUT my_index
{
"settings": {
"analysis": {
"char_filter": {
// Özel character filter tanımları
},
"tokenizer": {
// Özel tokenizer tanımları
},
"filter": {
// Özel token filter tanımları
},
"analyzer": {
"my_custom_analyzer": {
"type": "custom",
"char_filter": ["my_char_filter"],
"tokenizer": "my_tokenizer",
"filter": ["my_filter_1", "my_filter_2"]
}
}
}
}
}Önemli: Custom bileşenler ve built-in bileşenler karıştırılabilir. Örneğin custom bir char_filter + built-in standard tokenizer + custom bir token filter kullanabilirsiniz.
2. Türkçe Arama Optimizasyonu
Turkish analyzer iyi bir başlangıçtır, ama gerçek dünya projeleri için yeterli olmayabilir. Özelleştirmemiz gereken noktalar:
Özel stop words listesi
Karakter normalizasyonu (noktalama, özel karakterler)
Türkçe stemmer fine-tuning
Lowercase sorununun çözümü
2.1 Gelişmiş Türkçe Analyzer
PUT turkish_search_index
{
"settings": {
"analysis": {
"char_filter": {
"turkce_karakter_fix": {
"type": "mapping",
"mappings": [
"İ => i",
"I => ı",
"â => a",
"û => u",
"î => i",
"& => ve"
]
}
},
"filter": {
"turkish_lowercase": {
"type": "lowercase",
"language": "turkish"
},
"turkish_stop": {
"type": "stop",
"stopwords": [
"acaba", "ama", "ancak", "arada", "aslında",
"bazı", "belki", "ben", "beni", "benim",
"bir", "birçok", "birkaç", "birşey", "biz",
"bu", "buna", "bunda", "bundan", "bunlar",
"bunu", "bunun", "burada", "çok", "çünkü",
"da", "daha", "de", "defa", "değil",
"diğer", "diye", "dolayı", "eğer", "en",
"fakat", "filan", "gibi", "göre", "hala",
"hatta", "hem", "henüz", "hep", "hepsi",
"her", "hiç", "için", "ile", "ise",
"işte", "kadar", "karşın", "kendi", "kim",
"nasıl", "ne", "neden", "nerde", "nerede",
"nereye", "niçin", "niye", "o", "ona",
"ondan", "onlar", "onun", "onu", "oysa",
"öyle", "sen", "seni", "senin", "siz",
"şey", "şu", "tüm", "ve", "veya",
"ya", "yani"
]
},
"turkish_stemmer": {
"type": "stemmer",
"language": "turkish"
},
"word_min_length": {
"type": "length",
"min": 2
}
},
"analyzer": {
"turkce_analyzer": {
"type": "custom",
"char_filter": ["turkce_karakter_fix"],
"tokenizer": "standard",
"filter": [
"turkish_lowercase",
"turkish_stop",
"turkish_stemmer",
"word_min_length"
]
}
}
}
},
"mappings": {
"properties": {
"baslik": {
"type": "text",
"analyzer": "turkce_analyzer"
},
"icerik": {
"type": "text",
"analyzer": "turkce_analyzer"
}
}
}
}Test edelim:
POST turkish_search_index/_analyze
{
"analyzer": "turkce_analyzer",
"text": "Türkiye'deki yazılımcılar İstanbul'da buluşuyorlar"
}Çıktı: ["türkiye'deki", "yazılımcı", "istanbul'da", "buluş"]
Stemmer "yazılımcılar" → "yazılımcı" ve "buluşuyorlar" → "buluş" dönüşümünü yaptı. Stop words ("da") çıkarıldı.
2.2 Türkçe Normalization Filter — Ascifolding Alternatifi
Bazen kullanıcılar Türkçe karakterleri yanlış yazar (örneğin "calisma" yerine "çalışma"). Bunu tolere etmek için:
PUT tolerant_turkish_index
{
"settings": {
"analysis": {
"filter": {
"turkish_lowercase": {
"type": "lowercase",
"language": "turkish"
},
"ascii_fold": {
"type": "asciifolding",
"preserve_original": true
},
"turkish_stop": {
"type": "stop",
"stopwords": "_turkish_"
},
"turkish_stemmer": {
"type": "stemmer",
"language": "turkish"
}
},
"analyzer": {
"tolerant_turkce": {
"type": "custom",
"tokenizer": "standard",
"filter": [
"turkish_lowercase",
"ascii_fold",
"turkish_stop",
"turkish_stemmer"
]
}
}
}
}
}preserve_original: true sayesinde hem orijinal hem ASCII versiyonu saklanır:
POST tolerant_turkish_index/_analyze
{
"analyzer": "tolerant_turkce",
"text": "çalışma"
}Çıktı: ["çalış", "calis"] — Hem "çalış" hem "calis" token'ı üretildi. Artık "calisma" araması da sonuç döndürür.
⚠️ Dikkat: asciifolding Türkçe bağlamda dikkatli kullanılmalıdır. "ı" → "i" dönüşümü anlam kaymasına yol açabilir ("sıla" vs "sila").
3. Synonym (Eşanlamlı) Desteği
Kullanıcılar aynı şeyi farklı kelimelerle arayabilir: "telefon" = "cep telefonu" = "mobil", "bilgisayar" = "pc" = "laptop". Synonym filter bu sorunu çözer.
3.1 Inline Synonym Tanımı
PUT synonym_demo_index
{
"settings": {
"analysis": {
"filter": {
"turkish_lowercase": {
"type": "lowercase",
"language": "turkish"
},
"my_synonyms": {
"type": "synonym",
"synonyms": [
"telefon, cep telefonu, mobil, handset",
"bilgisayar, pc, laptop, dizüstü",
"araba, otomobil, araç",
"ev, konut, daire, residence",
"hızlı, süratli, çabuk, jet gibi",
"ucuz, ekonomik, uygun fiyatlı, bütçe dostu"
]
}
},
"analyzer": {
"synonym_analyzer": {
"type": "custom",
"tokenizer": "standard",
"filter": ["turkish_lowercase", "my_synonyms"]
}
}
}
},
"mappings": {
"properties": {
"title": {
"type": "text",
"analyzer": "synonym_analyzer"
}
}
}
}Test edelim:
// Veri ekle
POST synonym_demo_index/_doc/1
{ "title": "Samsung Galaxy akıllı telefon" }
POST synonym_demo_index/_doc/2
{ "title": "Uygun fiyatlı dizüstü bilgisayar" }
// "mobil" ile ara — "telefon" içeren dokümanı bulur
GET synonym_demo_index/_search
{
"query": {
"match": {
"title": "mobil"
}
}
}
// "laptop" ile ara — "bilgisayar" içeren dokümanı bulur
GET synonym_demo_index/_search
{
"query": {
"match": {
"title": "laptop"
}
}
}3.2 Synonym Dosyası Kullanımı
Production ortamında synonym'leri dosyadan yüklemek daha pratiktir:
PUT synonym_file_index
{
"settings": {
"analysis": {
"filter": {
"file_synonyms": {
"type": "synonym",
"synonyms_path": "analysis/synonyms_tr.txt",
"updateable": true
}
},
"analyzer": {
"search_synonym_analyzer": {
"type": "custom",
"tokenizer": "standard",
"filter": ["lowercase", "file_synonyms"]
}
}
}
},
"mappings": {
"properties": {
"title": {
"type": "text",
"analyzer": "standard",
"search_analyzer": "search_synonym_analyzer"
}
}
}
}config/analysis/synonyms_tr.txt dosyası:
# Eşanlamlılar (virgülle ayrılmış = çift yönlü)
telefon, cep telefonu, mobil
bilgisayar, pc, laptop, dizüstü
# Tek yönlü eşanlamlılar (=> ile)
ES => Elasticsearch
K8s => Kubernetes
JS => JavaScript3.3 Index-Time vs Search-Time Synonym
Bu ayrım çok kritik bir karardır:
Index-time synonym:
"title": {
"type": "text",
"analyzer": "synonym_analyzer" // Synonym index-time'da uygulanır
}✅ Arama hızlıdır (token'lar önceden genişletilmiş)
❌ Yeni synonym ekleyince tüm veriyi reindex etmeniz gerekir
❌ Term frequency etkilenir, scoring bozulabilir
Search-time synonym (önerilen):
"title": {
"type": "text",
"analyzer": "standard",
"search_analyzer": "synonym_analyzer" // Synonym sadece arama sırasında
}✅ Yeni synonym ekleyince reindex gerekmez
✅ Scoring daha doğru olur
❌ Arama biraz daha yavaş (sorgu genişletme maliyeti)
💡 İpucu: Çoğu durumda search-time synonym tercih edin. Synonym listeniz sık değişiyorsa bu yaklaşım zorunludur.
3.4 synonym_graph — Çok Kelimeli Eşanlamlılar
synonym filter tek kelimeli eşanlamlılarda iyi çalışır, ama "New York" = "NYC" gibi çok kelimeli durumlarda synonym_graph gerekir:
PUT graph_synonym_index
{
"settings": {
"analysis": {
"filter": {
"graph_synonyms": {
"type": "synonym_graph",
"synonyms": [
"New York, NYC, NY",
"cep telefonu, mobil cihaz, smartphone",
"yapay zeka, artificial intelligence, AI"
]
}
},
"analyzer": {
"graph_search_analyzer": {
"type": "custom",
"tokenizer": "standard",
"filter": ["lowercase", "graph_synonyms"]
}
}
}
},
"mappings": {
"properties": {
"content": {
"type": "text",
"analyzer": "standard",
"search_analyzer": "graph_search_analyzer"
}
}
}
}⚠️ Önemli: synonym_graph sadece search-time'da kullanılmalıdır. Index-time'da kullanmak pozisyon grafik sorunlarına yol açar.
4. Autocomplete (Search-as-You-Type) Analyzer
Kullanıcı henüz kelimeyi bitirmeden sonuç göstermek modern aramanın olmazsa olmazıdır. "Elast" yazıldığında "Elasticsearch" önerilmelidir.
4.1 Edge N-gram Yaklaşımı
PUT autocomplete_index
{
"settings": {
"analysis": {
"filter": {
"autocomplete_filter": {
"type": "edge_ngram",
"min_gram": 2,
"max_gram": 15
},
"turkish_lowercase": {
"type": "lowercase",
"language": "turkish"
}
},
"analyzer": {
"autocomplete_index_analyzer": {
"type": "custom",
"tokenizer": "standard",
"filter": [
"turkish_lowercase",
"autocomplete_filter"
]
},
"autocomplete_search_analyzer": {
"type": "custom",
"tokenizer": "standard",
"filter": [
"turkish_lowercase"
]
}
}
}
},
"mappings": {
"properties": {
"product_name": {
"type": "text",
"analyzer": "autocomplete_index_analyzer",
"search_analyzer": "autocomplete_search_analyzer"
}
}
}
}Neden iki farklı analyzer?
Index-time: "Samsung" →
["sa", "sam", "sams", "samsu", "samsun", "samsung"]Search-time: "sam" →
["sam"](edge_ngram uygulanmaz!)
Eğer search-time'da da edge_ngram kullansaydınız: "Samsung" araması → ["sa", "sam", "sams", ...] token'larına bölünür → "sa" prefix'li her şeyi bulur (saatler, sandalet, vb.).
Test edelim:
// Veri ekle
POST autocomplete_index/_bulk
{"index":{}}
{"product_name": "Samsung Galaxy S24 Ultra"}
{"index":{}}
{"product_name": "Samsung Galaxy Tab S9"}
{"index":{}}
{"product_name": "Apple iPhone 15 Pro"}
{"index":{}}
{"product_name": "Apple MacBook Air M3"}
{"index":{}}
{"product_name": "Sony PlayStation 5"}
// "sam" yaz → Samsung ürünleri gelir
GET autocomplete_index/_search
{
"query": {
"match": {
"product_name": "sam"
}
}
}
// "apple mac" yaz → MacBook gelir
GET autocomplete_index/_search
{
"query": {
"match": {
"product_name": "apple mac"
}
}
}4.2 Completion Suggester Alternatifi
Edge ngram dışında, Elasticsearch'ün completion field type'ı da autocomplete için kullanılabilir:
PUT suggest_index
{
"mappings": {
"properties": {
"suggest": {
"type": "completion",
"analyzer": "standard",
"contexts": [
{
"name": "category",
"type": "category"
}
]
},
"title": {
"type": "text"
}
}
}
}
// Veri ekle
POST suggest_index/_doc/1
{
"title": "Elasticsearch Temelleri",
"suggest": {
"input": ["Elasticsearch", "ES", "Elastic"],
"contexts": {
"category": ["teknoloji"]
},
"weight": 10
}
}
// Suggestion al
POST suggest_index/_search
{
"suggest": {
"product_suggest": {
"prefix": "ela",
"completion": {
"field": "suggest",
"size": 5,
"contexts": {
"category": ["teknoloji"]
}
}
}
}
}Edge N-gram vs Completion Suggester:
| Özellik | Edge N-gram | Completion Suggester |
|---|---|---|
| Hız | Hızlı | Çok hızlı (FST yapısı) |
| Esneklik | Yüksek (scoring, fuzzy) | Sınırlı |
| Index boyutu | Büyük (çok token) | Küçük |
| Fuzzy match | Query-time fuzzy | Built-in fuzzy |
| Scoring | TF-IDF scoring | Weight-based |
5. E-Ticaret Arama Analyzer'ı — Kapsamlı Örnek
Gerçek bir e-ticaret sitesi için farklı ihtiyaçları karşılayan multiple analyzer tanımlayalım:
PUT ecommerce_v2
{
"settings": {
"analysis": {
"char_filter": {
"html_cleaner": {
"type": "html_strip"
},
"special_chars": {
"type": "mapping",
"mappings": [
"& => ve",
"₺ => TL",
"\" => ",
"' => "
]
}
},
"filter": {
"turkish_lowercase": {
"type": "lowercase",
"language": "turkish"
},
"turkish_stop": {
"type": "stop",
"stopwords": "_turkish_"
},
"turkish_stemmer": {
"type": "stemmer",
"language": "turkish"
},
"product_synonyms": {
"type": "synonym_graph",
"synonyms": [
"telefon, cep telefonu, mobil, smartphone",
"bilgisayar, pc, laptop, dizüstü, notebook",
"tv, televizyon, ekran",
"kulaklık, earphone, headphone, earbuds",
"şarj, charging, powerbank",
"kılıf, case, kapak, cover"
]
},
"autocomplete_edge": {
"type": "edge_ngram",
"min_gram": 2,
"max_gram": 12
},
"min_length": {
"type": "length",
"min": 2
}
},
"analyzer": {
"product_index_analyzer": {
"type": "custom",
"char_filter": ["html_cleaner", "special_chars"],
"tokenizer": "standard",
"filter": [
"turkish_lowercase",
"turkish_stop",
"turkish_stemmer",
"min_length"
]
},
"product_search_analyzer": {
"type": "custom",
"char_filter": ["special_chars"],
"tokenizer": "standard",
"filter": [
"turkish_lowercase",
"turkish_stop",
"turkish_stemmer",
"product_synonyms",
"min_length"
]
},
"autocomplete_index_analyzer": {
"type": "custom",
"tokenizer": "standard",
"filter": [
"turkish_lowercase",
"autocomplete_edge"
]
},
"autocomplete_search_analyzer": {
"type": "custom",
"tokenizer": "standard",
"filter": [
"turkish_lowercase"
]
}
}
}
},
"mappings": {
"properties": {
"product_name": {
"type": "text",
"analyzer": "product_index_analyzer",
"search_analyzer": "product_search_analyzer",
"fields": {
"autocomplete": {
"type": "text",
"analyzer": "autocomplete_index_analyzer",
"search_analyzer": "autocomplete_search_analyzer"
},
"exact": {
"type": "keyword"
}
}
},
"description": {
"type": "text",
"analyzer": "product_index_analyzer",
"search_analyzer": "product_search_analyzer"
},
"category": {
"type": "keyword"
},
"brand": {
"type": "keyword"
},
"price": {
"type": "float"
}
}
}
}Bu tasarımda:
product_name→ Türkçe stemming + stop words (ana arama)product_name.autocomplete→ Edge ngram (autocomplete)product_name.exact→ Keyword (tam eşleşme, aggregation)Search-time'da synonym desteği (reindex gerekmez)
Veri ve Test
// Veri ekle
POST ecommerce_v2/_bulk
{"index":{"_id":"1"}}
{"product_name":"Samsung Galaxy S24 Ultra Akıllı Telefon","description":"<p>Samsung'un en güçlü <b>akıllı telefon</b> modeli</p>","category":"Elektronik","brand":"Samsung","price":54999.99}
{"index":{"_id":"2"}}
{"product_name":"Apple iPhone 15 Pro Max Cep Telefonu","description":"<p>Apple'ın en gelişmiş <em>mobil cihazı</em></p>","category":"Elektronik","brand":"Apple","price":64999.99}
{"index":{"_id":"3"}}
{"product_name":"Lenovo ThinkPad X1 Carbon Dizüstü Bilgisayar","description":"<p>İş dünyası için en iyi <b>laptop</b></p>","category":"Bilgisayar","brand":"Lenovo","price":42999.99}
// "mobil" araması → telefon dokümanlarını bulur (synonym)
GET ecommerce_v2/_search
{
"query": {
"match": {
"product_name": "mobil"
}
}
}
// Autocomplete: "sams" → Samsung ürünleri
GET ecommerce_v2/_search
{
"query": {
"match": {
"product_name.autocomplete": "sams"
}
}
}
// "laptop" araması → "bilgisayar" ve "dizüstü" dokümanlarını bulur
GET ecommerce_v2/_search
{
"query": {
"match": {
"product_name": "laptop"
}
}
}6. N-gram Analyzer — Fuzzy-Like Arama
N-gram, kelimenin ortasından da eşleşme sağlar. "elastic" araması "Elasticsearch" içinde de eşleşir. Autocomplete'ten farkı: edge_ngram sadece baştan eşleşirken, ngram her yerden eşleşir.
6.1 N-gram Analyzer Oluşturma
PUT ngram_index
{
"settings": {
"analysis": {
"filter": {
"ngram_filter": {
"type": "ngram",
"min_gram": 3,
"max_gram": 4
}
},
"analyzer": {
"ngram_analyzer": {
"type": "custom",
"tokenizer": "standard",
"filter": [
"lowercase",
"ngram_filter"
]
},
"ngram_search": {
"type": "custom",
"tokenizer": "standard",
"filter": ["lowercase"]
}
}
}
},
"mappings": {
"properties": {
"name": {
"type": "text",
"analyzer": "ngram_analyzer",
"search_analyzer": "ngram_search"
}
}
}
}POST ngram_index/_analyze
{
"analyzer": "ngram_analyzer",
"text": "Elasticsearch"
}Çıktı (kısaltılmış): ["ela", "elas", "las", "last", "ast", "asti", ...]
⚠️ Dikkat: N-gram index boyutunu dramatik şekilde artırır. min_gram: 3, max_gram: 4 bile 10+ kelimelik bir metni yüzlerce token'a dönüştürür. Sadece kısa alanlar (isim, ürün kodu) için kullanın.
7. Normalizer — Keyword Alanları İçin Hafif Analiz
keyword field type'ı analyze edilmez, ama bazen case-insensitive veya accent-insensitive karşılaştırma istersiniz. Bunun için normalizer kullanılır:
PUT normalizer_index
{
"settings": {
"analysis": {
"normalizer": {
"lowercase_normalizer": {
"type": "custom",
"char_filter": [],
"filter": ["lowercase", "asciifolding"]
}
}
}
},
"mappings": {
"properties": {
"brand": {
"type": "keyword",
"normalizer": "lowercase_normalizer"
},
"email": {
"type": "keyword",
"normalizer": "lowercase_normalizer"
}
}
}
}Artık:
POST normalizer_index/_doc/1
{ "brand": "Samsung", "email": "User@Email.COM" }
// Küçük harfle arama yapabilirsiniz
GET normalizer_index/_search
{
"query": {
"term": {
"brand": "samsung"
}
}
}
// ✅ Bulur! Çünkü normalizer "Samsung" → "samsung" dönüşümü yaptıNormalizer vs Analyzer:
Normalizer: Keyword field'lar için, tokenize etmez, sadece normalize eder
Analyzer: Text field'lar için, tokenize eder ve transform eder
8. Analyzer'ı Güncelleme ve Yönetim
8.1 Mevcut Index'e Analyzer Ekleme
Mevcut bir index'in settings'ini değiştirmek için index'i önce kapatmanız gerekir:
// 1. Index'i kapat
POST my_index/_close
// 2. Analyzer ekle/güncelle
PUT my_index/_settings
{
"analysis": {
"filter": {
"new_synonym_filter": {
"type": "synonym",
"synonyms": ["hızlı, çabuk, süratli"]
}
},
"analyzer": {
"new_analyzer": {
"type": "custom",
"tokenizer": "standard",
"filter": ["lowercase", "new_synonym_filter"]
}
}
}
}
// 3. Index'i aç
POST my_index/_open⚠️ Dikkat: Analyzer eklenmesi mevcut dokümanları etkilemez. Yeni analyzer'la index'lenmesi için dokümanlar yeniden index'lenmelidir.
8.2 Reloadable Synonym
Synonym dosyası değiştiğinde reindex yerine sadece reload yapabilirsiniz:
// Synonym filter'ı "updateable: true" ile tanımla (search_analyzer'da)
// Sonra reload:
POST my_index/_reload_search_analyzersBu sadece search-time analyzer'lar için çalışır — index-time analyzer'lar reload edilemez.
9. Java ile Custom Analyzer
import co.elastic.clients.elasticsearch.ElasticsearchClient;
import co.elastic.clients.elasticsearch.indices.*;
public class CustomAnalyzerJava {
public static void createCustomAnalyzerIndex(ElasticsearchClient client) throws Exception {
client.indices().create(c -> c
.index("products_custom")
.settings(s -> s
.analysis(a -> a
// Character filter
.charFilter("html_strip_filter", cf -> cf
.definition(d -> d
.htmlStrip(hs -> hs)
)
)
// Token filters
.filter("tr_lowercase", f -> f
.definition(d -> d
.lowercase(l -> l.language("turkish"))
)
)
.filter("tr_stop", f -> f
.definition(d -> d
.stop(st -> st.stopwords("_turkish_"))
)
)
.filter("tr_stemmer", f -> f
.definition(d -> d
.stemmer(st -> st.language("turkish"))
)
)
.filter("edge_ngram_filter", f -> f
.definition(d -> d
.edgeNGram(e -> e
.minGram(2)
.maxGram(12)
)
)
)
// Analyzers
.analyzer("turkish_custom", an -> an
.custom(cu -> cu
.charFilter("html_strip_filter")
.tokenizer("standard")
.filter("tr_lowercase", "tr_stop", "tr_stemmer")
)
)
.analyzer("autocomplete_idx", an -> an
.custom(cu -> cu
.tokenizer("standard")
.filter("tr_lowercase", "edge_ngram_filter")
)
)
.analyzer("autocomplete_srch", an -> an
.custom(cu -> cu
.tokenizer("standard")
.filter("tr_lowercase")
)
)
)
)
.mappings(m -> m
.properties("name", p -> p
.text(t -> t
.analyzer("turkish_custom")
.fields("autocomplete", f -> f
.text(t2 -> t2
.analyzer("autocomplete_idx")
.searchAnalyzer("autocomplete_srch")
)
)
)
)
)
);
System.out.println("Custom analyzer index oluşturuldu.");
}
}10. Best Practices
✅ Yapın
| Uygulama | Neden |
|---|---|
| Synonym'leri search-time'da uygulayın | Yeni synonym ekleyince reindex gerekmez |
| Autocomplete için farklı index/search analyzer kullanın | Index'te edge_ngram, search'te normal analyzer |
Türkçe için turkish_lowercase filter kullanın | I → ı dönüşümü doğru yapılır |
_analyze API ile her adımı test edin | Beklenmedik sonuçları erken yakalayın |
| Synonym dosyalarını versiyon kontrolünde tutun | Değişiklik geçmişi önemlidir |
❌ Yapmayın
| Uygulama | Neden |
|---|---|
| N-gram'ı uzun metin alanlarında kullanmayın | Index boyutu patlar |
synonym_graph'ı index-time'da kullanmayın | Pozisyon grafik sorunları yaratır |
asciifolding'i Türkçe'de dikkatli kullanın | "ı" → "i" anlam kaybına yol açabilir |
| Analyzer'ı production'da sık değiştirmeyin | Reindex gerektirir |
11. Yaygın Hatalar
Hata 1: Synonym Filter Sırası
// ❌ Synonym'den sonra stemmer — synonym token'ları stem edilir
"filter": ["lowercase", "my_synonyms", "stemmer"]
// ✅ Stemmer'dan sonra synonym (veya synonym'i search-time'a taşıyın)
"filter": ["lowercase", "stemmer", "my_synonyms"]Hata 2: Edge N-gram Search Analyzer'ı
// ❌ Search-time'da da edge_ngram kullanmak
"product_name": {
"type": "text",
"analyzer": "autocomplete_analyzer" // Hem index hem search aynı
}
// ✅ Farklı search analyzer
"product_name": {
"type": "text",
"analyzer": "autocomplete_index_analyzer",
"search_analyzer": "autocomplete_search_analyzer"
}Hata 3: Çok Fazla Token Filter
// ❌ Her şeyi bir analyzer'a tıkmak
"filter": [
"lowercase", "stop", "stemmer", "synonym",
"ngram", "edge_ngram", "asciifolding", "unique",
"trim", "truncate", "word_delimiter"
]Bu hem performansı düşürür hem de beklenmedik token dönüşümlerine yol açar. Analyzer'ları amaca göre ayrı tutun.
Hata 4: max_gram Değerini Çok Yüksek Tutmak
// ❌ 20 karakterlik edge_ngram
"type": "edge_ngram",
"min_gram": 1,
"max_gram": 20
// ✅ Makul aralık
"type": "edge_ngram",
"min_gram": 2,
"max_gram": 12min_gram: 1 tek harflik token üretir — çoğu durumda anlamsızdır ve index'i gereksiz büyütür.
12. Performans Karşılaştırması
| Yaklaşım | Index Boyutu (1M doküman) | Index Hızı | Arama Hızı |
|---|---|---|---|
| Standard analyzer | 1x (baz) | Hızlı | Hızlı |
| Turkish analyzer | 0.8x | Normal | Hızlı |
| Edge ngram (2-12) | 3-5x | Yavaş | Çok hızlı |
| Full ngram (3-5) | 8-15x | Çok yavaş | Hızlı |
| Synonym (search-time) | 1x | Hızlı | Biraz yavaş |
| Synonym (index-time) | 1.2-1.5x | Biraz yavaş | Hızlı |
💡 İpucu: Autocomplete için edge_ngram kullanıyorsanız, sadece kısa alanlar (başlık, isim) için uygulayın. Uzun açıklama alanlarına uygulamayın.
Özet
Custom analyzer = char_filter(s) + tokenizer + token_filter(s) kombinasyonu — built-in'ler yetmediğinde devreye girer
Türkçe arama için
turkish_lowercase+ custom stop words +turkish_stemmerkombinasyonu kullanınSynonym desteği için
synonym_graphfilter'ı tercih edin ve search-time'da uygulayın — yeni eşanlamlı ekleyince reindex gerekmezAutocomplete için edge_ngram kullanın — index-time'da edge_ngram, search-time'da normal analyzer
Normalizer, keyword field'lar için hafif normalizasyon sağlar (case-insensitive tam eşleşme)
Analyzer güncellemesi index kapatma/açma gerektirir — production'da dikkatli planlayın
Her analyzer'ı `_analyze` API ile test edin — beklenmedik token dönüşümlerini erken yakalayın
AI Asistan
Sorularını yanıtlamaya hazır