Percolate Query ve More Like This
Giriş — Aramayı Tersine Çevirmek
Normalde arama şöyle çalışır: dokümanlar index'te durur, siz sorgu yazarsınız, eşleşen dokümanlar gelir. Peki ya tam tersini yapmak isterseniz? Sorguları saklayıp, yeni bir doküman geldiğinde hangi sorgularla eşleştiğini bulmak?
Bir haber sitesi düşünün. Kullanıcı "Yapay zeka ve sağlık" konusunu takip etmek istiyor. Bu aslında bir sorgudur. Yeni bir haber eklendiğinde, o haberin hangi kullanıcıların ilgi alanıyla eşleştiğini bulmak istiyorsunuz — işte bu percolate query'dir. Arama tersine dönmüş: doküman sabit değil sorgu, sorgu sabit değil doküman.
İkinci konumuz More Like This sorgusu. "Bu dokümanla benzer dokümanları bul" diyen, öneri sistemlerinin (recommendation engine) temelini oluşturan bir sorgudur. Netflix'in "bunu beğendiyseniz, bunları da beğenebilirsiniz" özelliğinin basit hali.
1. Percolate Query — Reverse Search
1.1 Kavram
Normal arama:
Sabit: Dokümanlar (index'te)
Değişken: Sorgu (kullanıcıdan)
Sonuç: Sorguyla eşleşen dokümanlarPercolate (ters arama):
Sabit: Sorgular (index'te)
Değişken: Doküman (yeni gelen)
Sonuç: Dokümanla eşleşen sorgularGerçek hayat analojisi: Bir güvenlik kamerası sistemi düşünün. Kameranın önünden yüzlerce insan geçiyor. Sistemde "aranan kişilerin" fotoğrafları kayıtlı. Her yeni yüz tespit edildiğinde, kayıtlı fotoğraflarla karşılaştırılır. İşte percolate query tam bunu yapar — yeni dokümanları kayıtlı sorgularla karşılaştırır.
1.2 Percolator Field Type
Percolate query kullanmak için index'te percolator tipinde bir field tanımlamanız gerekir:
PUT alerts
{
"mappings": {
"properties": {
"query": {
"type": "percolator"
},
"title": {
"type": "text",
"analyzer": "turkish"
},
"category": {
"type": "keyword"
},
"source": {
"type": "keyword"
}
}
}
}query field'ı percolator tipindedir — burada Elasticsearch sorguları saklanır. Diğer field'lar (title, category, source) gelen dokümanların field'larıdır.
1.3 Sorguları Kaydetme
// Kullanıcı 1: "Yapay zeka" haberlerini takip ediyor
POST alerts/_doc/user1_ai
{
"query": {
"match": {
"title": "yapay zeka"
}
},
"user_id": "user1",
"alert_name": "Yapay Zeka Haberleri"
}
// Kullanıcı 2: "Ekonomi" kategorisindeki haberleri takip ediyor
POST alerts/_doc/user2_economy
{
"query": {
"bool": {
"must": [
{ "term": { "category": "ekonomi" } }
]
}
},
"user_id": "user2",
"alert_name": "Ekonomi Haberleri"
}
// Kullanıcı 3: "Sağlık" VE "teknoloji" kombinasyonu
POST alerts/_doc/user3_health_tech
{
"query": {
"bool": {
"must": [
{ "match": { "title": "sağlık" } },
{ "match": { "title": "teknoloji" } }
]
}
},
"user_id": "user3",
"alert_name": "Sağlık Teknolojisi"
}
// Kullanıcı 4: Belirli kaynaktan "deprem" haberleri
POST alerts/_doc/user4_earthquake
{
"query": {
"bool": {
"must": [
{ "match": { "title": "deprem" } }
],
"filter": [
{ "term": { "source": "afad" } }
]
}
},
"user_id": "user4",
"alert_name": "AFAD Deprem Bildirimleri"
}1.4 Percolate Sorgusu — Yeni Doküman Test Etme
Yeni bir haber geldi. Hangi kullanıcıların ilgi alanıyla eşleşiyor?
GET alerts/_search
{
"query": {
"percolate": {
"field": "query",
"document": {
"title": "Yapay zeka teknolojisi sağlık sektöründe devrim yaratıyor",
"category": "teknoloji",
"source": "bbc"
}
}
}
}Sonuç: user1_ai (yapay zeka eşleşti), user3_health_tech (sağlık + teknoloji eşleşti). user2 ve user4 eşleşmedi çünkü kategori "ekonomi" değil ve kaynak "afad" değil.
1.5 Birden Fazla Dokümanı Percolate Etme
GET alerts/_search
{
"query": {
"percolate": {
"field": "query",
"documents": [
{
"title": "Borsa'da sert düşüş yaşandı",
"category": "ekonomi",
"source": "reuters"
},
{
"title": "AFAD deprem raporu yayınladı",
"category": "gündem",
"source": "afad"
}
]
}
}
}Her doküman hangi sorgularla eşleştiğini _percolator_document_slot field'ından anlarsınız (0 = ilk doküman, 1 = ikinci doküman).
1.6 Mevcut Index'teki Dokümanla Percolate
Yeni bir doküman yerine, zaten index'te olan bir dokümanı test edebilirsiniz:
// Önce haber index'inde bir doküman olsun
PUT haberler/_doc/123
{
"title": "Yapay zeka ile kanser teşhisi",
"category": "sağlık",
"source": "medikal"
}
// Bu dokümanı alerts index'indeki sorgularla test et
GET alerts/_search
{
"query": {
"percolate": {
"field": "query",
"index": "haberler",
"id": "123"
}
}
}2. Real-time Alert Sistemi Kurma
Percolate query ile gerçek zamanlı bildirim sistemi kurmak:
2.1 Mimari
┌──────────────┐
Yeni Doküman ───►│ Ingest Node │
│ Pipeline │
└──────┬───────┘
│
┌────▼─────┐
│ Percolate │◄── Kayıtlı Sorgular
│ Query │ (alerts index)
└────┬─────┘
│
┌──────▼───────┐
│ Eşleşenler │
│ → Bildirim │
│ (email/push)│
└──────────────┘2.2 Alert Index Tasarımı
PUT realtime_alerts
{
"settings": {
"number_of_shards": 2,
"number_of_replicas": 1,
"analysis": {
"analyzer": {
"alert_analyzer": {
"type": "custom",
"tokenizer": "standard",
"filter": [
{"type": "lowercase", "language": "turkish"},
{"type": "stop", "stopwords": "_turkish_"},
{"type": "stemmer", "language": "turkish"}
]
}
}
}
},
"mappings": {
"properties": {
"query": { "type": "percolator" },
"title": { "type": "text", "analyzer": "alert_analyzer" },
"content": { "type": "text", "analyzer": "alert_analyzer" },
"category": { "type": "keyword" },
"tags": { "type": "keyword" },
"priority": { "type": "keyword" },
"user_id": { "type": "keyword" },
"alert_name": { "type": "text" },
"created_at": { "type": "date" },
"notification_channel": { "type": "keyword" }
}
}
}
// Kullanıcı alert'lerini kaydet
POST realtime_alerts/_bulk
{"index":{"_id":"alert_1"}}
{"query":{"bool":{"must":[{"match":{"title":"yapay zeka"}}],"filter":[{"term":{"category":"teknoloji"}}]}},"user_id":"u001","alert_name":"AI Haberleri","notification_channel":"email","priority":"high"}
{"index":{"_id":"alert_2"}}
{"query":{"match_phrase":{"title":"döviz kuru"}},"user_id":"u002","alert_name":"Döviz Takibi","notification_channel":"push","priority":"urgent"}
{"index":{"_id":"alert_3"}}
{"query":{"bool":{"should":[{"match":{"tags":"deprem"}},{"match":{"tags":"sel"}},{"match":{"tags":"fırtına"}}],"minimum_should_match":1}},"user_id":"u003","alert_name":"Doğal Afet","notification_channel":"sms","priority":"urgent"}2.3 Yeni İçerik Geldiğinde
// Yeni haber geldi — hangi alert'lerle eşleşiyor?
GET realtime_alerts/_search
{
"query": {
"percolate": {
"field": "query",
"document": {
"title": "Döviz kuru rekor kırdı, dolar 35 TL'yi aştı",
"content": "Merkez Bankası'nın faiz kararı sonrası döviz kurları...",
"category": "ekonomi",
"tags": ["döviz", "ekonomi", "dolar"]
}
}
},
"_source": ["user_id", "alert_name", "notification_channel", "priority"]
}Sonuçtan user_id, notification_channel ve priority bilgilerini alıp bildirim gönderirsiniz.
⚠️ Performans Notu: Percolate index'inde binlerce sorgu varsa, her yeni doküman için hepsini taramak maliyetlidir. Shard sayısını artırın ve filter context kullanarak arama alanını daraltın.
3. More Like This Query
3.1 Kavram
"Bu dokümanla benzer dokümanları bul" sorgusu. MLT (More Like This) dokümanın text field'larından önemli terimleri çıkarır ve bu terimlerle bir bool sorgusu oluşturur.
3.2 Temel Kullanım
// Önce bazı dokümanlar ekleyelim
PUT articles/_bulk
{"index":{"_id":"1"}}
{"title":"Python ile Makine Öğrenmesi","content":"Python, makine öğrenmesi ve yapay zeka projelerinde en çok kullanılan programlama dilidir. scikit-learn, TensorFlow ve PyTorch gibi kütüphaneler...","tags":["python","ml","ai"]}
{"index":{"_id":"2"}}
{"title":"Java Spring Boot Microservices","content":"Spring Boot ile mikroservis mimarisi kurmak. REST API, Docker, Kubernetes entegrasyonu...","tags":["java","spring","microservices"]}
{"index":{"_id":"3"}}
{"title":"TensorFlow ile Derin Öğrenme","content":"TensorFlow kullanarak derin öğrenme modelleri eğitmek. CNN, RNN, Transformer mimarileri ile yapay zeka uygulamaları...","tags":["python","deep-learning","ai"]}
{"index":{"_id":"4"}}
{"title":"Python Django Web Framework","content":"Django ile web uygulaması geliştirmek. ORM, template engine, authentication, REST API...","tags":["python","django","web"]}
{"index":{"_id":"5"}}
{"title":"Elasticsearch ile Arama Motoru","content":"Elasticsearch kullanarak full-text search, aggregation ve analiz. Inverted index, BM25 scoring...","tags":["elasticsearch","search","java"]}
// Doküman 1'e benzer dokümanları bul
GET articles/_search
{
"query": {
"more_like_this": {
"fields": ["title", "content", "tags"],
"like": [
{ "_index": "articles", "_id": "1" }
],
"min_term_freq": 1,
"min_doc_freq": 1,
"max_query_terms": 15
}
}
}Sonuç: Doküman 3 (TensorFlow, yapay zeka, derin öğrenme — benzer konular), Doküman 4 (Python — ortak dil) yüksek skorla gelir.
3.3 MLT Parametreleri
| Parametre | Varsayılan | Açıklama |
|---|---|---|
min_term_freq | 2 | Terim, kaynak dokümanda en az bu kadar geçmeli |
min_doc_freq | 5 | Terim, en az bu kadar dokümanda geçmeli |
max_doc_freq | unbounded | Terim, en fazla bu kadar dokümanda geçmeli (çok yaygın terimleri eler) |
max_query_terms | 25 | Oluşturulan sorgudaki maksimum terim sayısı |
min_word_length | 0 | Minimum kelime uzunluğu |
max_word_length | unbounded | Maksimum kelime uzunluğu |
boost_terms | 0 | Terimlere TF-IDF bazlı boost uygula |
minimum_should_match | "30%" | Minimum eşleşme oranı |
💡 İpucu: Küçük veri setlerinde min_term_freq: 1 ve min_doc_freq: 1 kullanın. Varsayılan değerler büyük veri setleri için tasarlanmıştır — küçük veri setlerinde hiç sonuç dönmeyebilir.
3.4 Metin Bazlı MLT
Doküman yerine doğrudan metin vererek de benzer doküman arayabilirsiniz:
GET articles/_search
{
"query": {
"more_like_this": {
"fields": ["title", "content"],
"like": [
"Python programlama dili ile yapay zeka ve makine öğrenmesi projeleri"
],
"min_term_freq": 1,
"min_doc_freq": 1,
"max_query_terms": 20
}
}
}3.5 Kombinasyon — Doküman + Metin
GET articles/_search
{
"query": {
"more_like_this": {
"fields": ["title", "content"],
"like": [
{ "_index": "articles", "_id": "1" },
"Derin öğrenme ve sinir ağları"
],
"unlike": [
{ "_index": "articles", "_id": "2" }
],
"min_term_freq": 1,
"min_doc_freq": 1
}
}
}unlike parametresi, belirli dokümanlardan uzaklaşmayı sağlar. "Doküman 1'e benzet ama doküman 2'ye benzetme" gibi.
4. Significant Terms Aggregation
Significant terms, bir doküman alt kümesinde istatistiksel olarak anlamlı olan terimleri bulur. Normal terms aggregation en yaygın terimleri döndürür, significant_terms ise "bu kümedeki dokümanları diğerlerinden farklı kılan" terimleri döndürür.
4.1 Temel Kullanım
GET articles/_search
{
"query": {
"match": { "tags": "python" }
},
"aggs": {
"significant_keywords": {
"significant_terms": {
"field": "content",
"size": 10,
"min_doc_count": 1
}
}
},
"size": 0
}Bu sorgu: "python" etiketli dokümanları al, bu dokümanların content field'ında hangi terimler tüm dokümanlara kıyasla anlamlı derecede fazla geçiyor? Muhtemelen "makine", "öğrenme", "tensorflow" gibi terimler çıkar.
4.2 Significant Terms vs Terms
// terms: En sık geçen kelimeler (genel)
"aggs": {
"common_words": {
"terms": { "field": "content", "size": 10 }
}
}
// Sonuç: "ve", "bir", "ile" gibi yaygın kelimeler (işe yaramaz)
// significant_terms: İstatistiksel olarak anlamlı kelimeler
"aggs": {
"special_words": {
"significant_terms": { "field": "content", "size": 10 }
}
}
// Sonuç: "tensorflow", "makine öğrenmesi", "model" gibi ayırt edici kelimeler4.3 Significant Text
significant_terms keyword/text field üzerinde token bazlı çalışır. significant_text ise runtime'da analiz yapar — field'ın fielddata: true olması gerekmez:
GET articles/_search
{
"query": {
"match": { "tags": "python" }
},
"aggs": {
"significant_phrases": {
"significant_text": {
"field": "content",
"filter_duplicate_text": true
}
}
},
"size": 0
}5. Benzer Doküman Bulma — Recommendation Engine Temelleri
5.1 Content-Based Recommendation
MLT + significant_terms ile basit ama etkili bir öneri sistemi:
PUT products
{
"mappings": {
"properties": {
"name": { "type": "text", "analyzer": "turkish" },
"description": { "type": "text", "analyzer": "turkish" },
"category": { "type": "keyword" },
"brand": { "type": "keyword" },
"price": { "type": "float" },
"tags": { "type": "keyword" },
"specs": { "type": "text" }
}
}
}
// Ürünler ekleyelim
POST products/_bulk
{"index":{"_id":"p1"}}
{"name":"Samsung Galaxy S24 Ultra","description":"6.8 inç AMOLED ekran, 200MP kamera, Snapdragon 8 Gen 3","category":"Telefon","brand":"Samsung","price":54999,"tags":["android","5g","flagship"],"specs":"12GB RAM 256GB depolama"}
{"index":{"_id":"p2"}}
{"name":"Apple iPhone 15 Pro Max","description":"6.7 inç Super Retina XDR, 48MP kamera, A17 Pro çip","category":"Telefon","brand":"Apple","price":64999,"tags":["ios","5g","flagship"],"specs":"8GB RAM 256GB depolama"}
{"index":{"_id":"p3"}}
{"name":"Samsung Galaxy Tab S9","description":"11 inç AMOLED tablet, S Pen, Snapdragon 8 Gen 2","category":"Tablet","brand":"Samsung","price":24999,"tags":["android","tablet"],"specs":"8GB RAM 128GB depolama"}
{"index":{"_id":"p4"}}
{"name":"Google Pixel 8 Pro","description":"6.7 inç LTPO OLED, 50MP kamera, Tensor G3 çip","category":"Telefon","brand":"Google","price":34999,"tags":["android","5g","flagship"],"specs":"12GB RAM 128GB depolama"}
{"index":{"_id":"p5"}}
{"name":"Samsung Galaxy Buds FE","description":"Kablosuz kulaklık, ANC, Samsung ekosistemi","category":"Aksesuar","brand":"Samsung","price":2499,"tags":["kulaklık","bluetooth"],"specs":"ANC destekli"}
// "Samsung Galaxy S24 Ultra" aldıysa, ne önerelim?
GET products/_search
{
"query": {
"more_like_this": {
"fields": ["description", "tags", "specs"],
"like": [
{ "_index": "products", "_id": "p1" }
],
"min_term_freq": 1,
"min_doc_freq": 1,
"max_query_terms": 20,
"minimum_should_match": "20%"
}
},
"_source": ["name", "brand", "price", "category"]
}Sonuç: iPhone 15 Pro (benzer flagship telefon), Pixel 8 Pro (benzer Android flagship) yüksek skorla gelir.
5.2 Kategori + MLT Kombinasyonu
// Aynı kategoride benzer ürünler (daha isabetli)
GET products/_search
{
"query": {
"bool": {
"must": [
{
"more_like_this": {
"fields": ["description", "tags", "specs"],
"like": [
{ "_index": "products", "_id": "p1" }
],
"min_term_freq": 1,
"min_doc_freq": 1
}
}
],
"filter": [
{ "term": { "category": "Telefon" } }
],
"must_not": [
{ "ids": { "values": ["p1"] } }
]
}
}
}must_not ile kaynak dokümanın kendisini sonuçlardan çıkarıyoruz.
5.3 "Bunu Beğendiyseniz" Pattern
Kullanıcının son 5 görüntülediği ürüne bakarak öneri:
GET products/_search
{
"query": {
"more_like_this": {
"fields": ["description", "tags", "category"],
"like": [
{ "_index": "products", "_id": "p1" },
{ "_index": "products", "_id": "p2" },
{ "_index": "products", "_id": "p4" }
],
"unlike": [
{ "_index": "products", "_id": "p3" }
],
"min_term_freq": 1,
"min_doc_freq": 1,
"max_query_terms": 25,
"boost_terms": 1
}
},
"size": 5
}Birden fazla like vererek kullanıcının ilgi profilini genişletiyoruz. boost_terms: 1 ile TF-IDF bazlı boosting ekliyoruz.
6. Java ile Percolate ve MLT
import co.elastic.clients.elasticsearch.ElasticsearchClient;
import co.elastic.clients.elasticsearch.core.*;
import co.elastic.clients.json.JsonData;
import java.util.Map;
// Percolate sorgusu — yeni dokümanla eşleşen alert'leri bul
SearchResponse<Map> percolateResponse = client.search(s -> s
.index("realtime_alerts")
.query(q -> q
.percolate(p -> p
.field("query")
.document(JsonData.of(Map.of(
"title", "Yapay zeka ile kanser teşhisi başarılı oldu",
"category", "sağlık",
"tags", java.util.List.of("yapay-zeka", "sağlık", "teknoloji")
)))
)
),
Map.class
);
System.out.println("Eşleşen alert'ler:");
percolateResponse.hits().hits().forEach(hit -> {
Map<String, Object> source = hit.source();
System.out.printf(" Alert: %s (Kullanıcı: %s, Kanal: %s)%n",
source.get("alert_name"),
source.get("user_id"),
source.get("notification_channel")
);
});
// More Like This sorgusu
SearchResponse<Map> mltResponse = client.search(s -> s
.index("products")
.query(q -> q
.moreLikeThis(mlt -> mlt
.fields("description", "tags", "specs")
.like(l -> l
.document(d -> d.index("products").id("p1"))
)
.minTermFreq(1)
.minDocFreq(1)
.maxQueryTerms(20)
)
)
.size(5),
Map.class
);
System.out.println("\nBenzer ürünler:");
mltResponse.hits().hits().forEach(hit -> {
Map<String, Object> source = hit.source();
System.out.printf(" [%.2f] %s - %s TL%n",
hit.score(), source.get("name"), source.get("price"));
});7. Yaygın Hatalar ve Çözümleri
Hata 1: MLT Sonuç Döndürmüyor
// ❌ Küçük veri setinde varsayılan parametreler çok yüksek
{
"more_like_this": {
"fields": ["description"],
"like": [{"_index": "articles", "_id": "1"}]
// min_term_freq: 2, min_doc_freq: 5 → çoğu terim elenebilir
}
}
// ✅ Küçük veri setleri için parametreleri düşürün
{
"more_like_this": {
"fields": ["description"],
"like": [{"_index": "articles", "_id": "1"}],
"min_term_freq": 1,
"min_doc_freq": 1,
"max_query_terms": 25
}
}Hata 2: Percolator Index'inde Analyzer Tanımlamamak
// ❌ Percolator index'inde title field'ına analyzer tanımlanmadı
// Ama dokümanı index'leyecek index'te analyzer var
// → Token'lar eşleşmez!
// ✅ Percolator index'teki field tipleri ve analyzer'lar,
// dokümanın geldiği index ile AYNI olmalıHata 3: MLT'de Kaynak Dokümanı Sonuçtan Çıkarmamak
// ❌ Kaynak doküman her zaman en yüksek skorla gelir (kendisiyle %100 benzer)
{
"more_like_this": {
"like": [{"_id": "1"}]
}
}
// ✅ must_not ile kendisini çıkarın
{
"bool": {
"must": [{ "more_like_this": { "like": [{"_id": "1"}] } }],
"must_not": [{ "ids": { "values": ["1"] } }]
}
}Hata 4: Percolate'te Çok Fazla Sorgu Biriktirmek
Binlerce percolate sorgusu performansı düşürür. Çözümler:
Shard sayısını artırın
Filter context kullanarak arama alanını daraltın
Kullanılmayan alert'leri periyodik olarak temizleyin
8. Best Practices
Percolate Query
| Uygulama | Neden |
|---|---|
| Percolator index'i ayrı tutun | Ana veri index'ini etkilemez |
| Filter context kullanın | Performansı artırır, arama alanını daraltır |
| Kullanılmayan sorguları temizleyin | Shard boyutu ve performans korunur |
| Mapping'leri senkronize tutun | Percolator ve kaynak index aynı analyzer kullanmalı |
More Like This
| Uygulama | Neden |
|---|---|
min_term_freq ve min_doc_freq veri boyutuna göre ayarlayın | Küçük veri setinde 1, büyükte varsayılan |
| Birden fazla field kullanın | Daha zengin benzerlik analizi |
unlike ile negatif sinyal verin | Daha isabetli öneriler |
boost_terms kullanın | TF-IDF bazlı terim ağırlıklandırma |
Kaynak dokümanı must_not ile çıkarın | Kendisiyle eşleşmeyi engelleyin |
Özet
Percolate Query aramayı tersine çevirir — sorgular index'te durur, yeni doküman geldiğinde hangi sorgularla eşleştiği bulunur
Percolator field type Elasticsearch sorgularını saklayan özel bir field tipidir
Real-time alert sistemi percolate query ile kurulur — yeni içerik → eşleşen kullanıcılar → bildirim
More Like This bir dokümanla benzer dokümanları bulur — recommendation engine temeli
MLT parametreleri veri boyutuna göre ayarlanmalı — küçük veri setlerinde
min_term_freq: 1Significant Terms bir alt kümedeki istatistiksel olarak anlamlı terimleri bulur — "ne farklı?" sorusuna cevap
unlike parametresi ile negatif sinyal vererek öneri kalitesini artırabilirsiniz
AI Asistan
Sorularını yanıtlamaya hazır