Multi-field Mapping — keyword + text Stratejileri
Giriş — Bir Fotoğrafın Birden Fazla Kullanımı
Bir düğün fotoğrafı çektirdiniz diyelim. O fotoğrafın orijinal halini albüme koyarsınız, küçültülmüş halini Instagram'a yüklersiniz, kırpılmış halini profil fotoğrafı yaparsınız. Aynı fotoğraf, farklı amaçlar için farklı şekillerde kullanılır — ama kaynak aynıdır.
Elasticsearch'te de bir alanın (field) değerini birden fazla şekilde index'leyebilirsiniz. Aynı title alanı hem full-text arama için text olarak, hem exact match ve aggregation için keyword olarak, hem de autocomplete için edge_ngram ile index'lenebilir. Buna multi-field mapping denir ve Elasticsearch'ün en güçlü mapping özelliklerinden biridir.
1. Multi-field Mapping Nedir?
Multi-field mapping, tek bir kaynak alanın birden fazla farklı konfigürasyonla index'lenmesini sağlar. Ana field'a ek olarak .fields altında alt alanlar tanımlanır:
PUT my_index
{
"mappings": {
"properties": {
"title": {
"type": "text",
"analyzer": "standard",
"fields": {
"keyword": {
"type": "keyword"
},
"turkish": {
"type": "text",
"analyzer": "turkish"
}
}
}
}
}
}Bu mapping'de title alanı üç farklı şekilde erişilebilir:
| Erişim Yolu | Tip | Analyzer | Kullanım |
|---|---|---|---|
title | text | standard | Genel full-text arama |
title.keyword | keyword | — | Exact match, aggregation, sorting |
title.turkish | text | turkish | Türkçe stemming ile arama |
2. Neden Multi-field Gerekli?
Problem: Tek Field, Çoklu İhtiyaç
Bir e-ticaret sitesinde brand alanını düşünün:
Arama: "samsu" yazınca "Samsung" bulunmalı →
texttype gerekirFiltreleme: Marka = "Samsung" (exact match) →
keywordtype gerekirAggregation: En popüler 10 marka →
keywordtype gerekirSıralama: Markaya göre A-Z sırala →
keywordtype gerekir
Tek bir field type ile tüm bunları yapamazsınız:
// ❌ Sadece text — aggregation ve exact match yapılamaz
"brand": { "type": "text" }
// ❌ Sadece keyword — full-text arama yapılamaz
"brand": { "type": "keyword" }Çözüm: Multi-field
// ✅ Her iki ihtiyacı da karşılar
"brand": {
"type": "text",
"fields": {
"raw": {
"type": "keyword"
}
}
}Artık:
brand→ full-text arama içinbrand.raw→ aggregation, sorting, exact match için
3. Dynamic Mapping ve Multi-field
Elasticsearch'ün dynamic mapping özelliği, string tipindeki alanları otomatik olarak multi-field yapar:
// Doküman ekle (mapping yok)
POST auto_index/_doc/1
{
"title": "Elasticsearch Temelleri",
"category": "Teknoloji"
}
// Mapping'i kontrol et
GET auto_index/_mappingSonuç:
{
"auto_index": {
"mappings": {
"properties": {
"title": {
"type": "text",
"fields": {
"keyword": {
"type": "keyword",
"ignore_above": 256
}
}
},
"category": {
"type": "text",
"fields": {
"keyword": {
"type": "keyword",
"ignore_above": 256
}
}
}
}
}
}
}Elasticsearch otomatik olarak her string alanı text + keyword multi-field olarak oluşturdu. ignore_above: 256 parametresi, 256 karakterden uzun değerlerin keyword olarak index'lenmemesini sağlar (çok uzun string'ler keyword'de anlamsızdır).
⚠️ Dikkat: Dynamic mapping prototipler için uygundur ama production'da explicit mapping tanımlayın. Dynamic mapping gereksiz field'lar oluşturabilir ve mapping explosion'a yol açabilir.
4. Multi-field Kullanım Kalıpları
4.1 text + keyword (En Yaygın)
PUT products_index
{
"mappings": {
"properties": {
"product_name": {
"type": "text",
"analyzer": "turkish",
"fields": {
"keyword": {
"type": "keyword",
"ignore_above": 256
}
}
}
}
}
}Kullanım:
// Full-text arama
GET products_index/_search
{
"query": {
"match": {
"product_name": "akıllı telefon"
}
}
}
// Exact match
GET products_index/_search
{
"query": {
"term": {
"product_name.keyword": "Samsung Galaxy S24 Ultra"
}
}
}
// Aggregation
GET products_index/_search
{
"size": 0,
"aggs": {
"popular_products": {
"terms": {
"field": "product_name.keyword",
"size": 10
}
}
}
}
// Sorting
GET products_index/_search
{
"sort": [
{ "product_name.keyword": "asc" }
]
}4.2 text + text (Farklı Analyzer'lar)
PUT multilang_index
{
"mappings": {
"properties": {
"description": {
"type": "text",
"analyzer": "standard",
"fields": {
"tr": {
"type": "text",
"analyzer": "turkish"
},
"en": {
"type": "text",
"analyzer": "english"
}
}
}
}
}
}Kullanım — Çok dilli arama:
GET multilang_index/_search
{
"query": {
"multi_match": {
"query": "geliştiriciler",
"fields": ["description", "description.tr^2", "description.en"],
"type": "best_fields"
}
}
}description.tr^2 ile Türkçe field'a 2x boost verildi. Türkçe stemming eşleşmesi daha yüksek skor alır.
4.3 text + keyword + autocomplete (Üçlü Combo)
PUT complete_mapping_index
{
"settings": {
"analysis": {
"filter": {
"autocomplete_filter": {
"type": "edge_ngram",
"min_gram": 2,
"max_gram": 12
},
"turkish_lowercase": {
"type": "lowercase",
"language": "turkish"
}
},
"analyzer": {
"autocomplete_index": {
"type": "custom",
"tokenizer": "standard",
"filter": ["turkish_lowercase", "autocomplete_filter"]
},
"autocomplete_search": {
"type": "custom",
"tokenizer": "standard",
"filter": ["turkish_lowercase"]
}
}
}
},
"mappings": {
"properties": {
"city": {
"type": "text",
"analyzer": "turkish",
"fields": {
"keyword": {
"type": "keyword"
},
"autocomplete": {
"type": "text",
"analyzer": "autocomplete_index",
"search_analyzer": "autocomplete_search"
}
}
}
}
}
}Kullanım senaryoları:
// Full-text arama (Türkçe stemming)
GET complete_mapping_index/_search
{
"query": { "match": { "city": "istanbullu" } }
}
// Autocomplete
GET complete_mapping_index/_search
{
"query": { "match": { "city.autocomplete": "ist" } }
}
// Aggregation (kaç farklı şehir var?)
GET complete_mapping_index/_search
{
"size": 0,
"aggs": {
"unique_cities": {
"terms": { "field": "city.keyword", "size": 100 }
}
}
}
// Sorting
GET complete_mapping_index/_search
{
"sort": [{ "city.keyword": "asc" }]
}4.4 keyword + normalizer (Case-Insensitive Exact Match)
PUT normalized_index
{
"settings": {
"analysis": {
"normalizer": {
"lowercase_normalizer": {
"type": "custom",
"filter": ["lowercase"]
}
}
}
},
"mappings": {
"properties": {
"email": {
"type": "keyword",
"fields": {
"normalized": {
"type": "keyword",
"normalizer": "lowercase_normalizer"
}
}
}
}
}
}Artık:
email→ Orijinal haliyle saklanır ("User@Email.COM")email.normalized→ Küçük harfe dönüştürülmüş ("user@email.com")
POST normalized_index/_doc/1
{ "email": "Ahmet.Yilmaz@Sirket.COM" }
// Orijinal halle exact match
GET normalized_index/_search
{
"query": { "term": { "email": "Ahmet.Yilmaz@Sirket.COM" } }
}
// Küçük harfle arama
GET normalized_index/_search
{
"query": { "term": { "email.normalized": "ahmet.yilmaz@sirket.com" } }
}5. Index-Time vs Search-Time Analysis Derinlemesine
Bu kavram multi-field mapping'in temel taşıdır. Doğru anlaşılmazsa arama kalitesi düşer.
5.1 Index-Time Analysis
Bir doküman index'lendiğinde, her text field'ın değeri o field'ın analyzer'ından geçer ve oluşan token'lar inverted index'e yazılır.
Doküman: { "title": "Elasticsearch Kurulum Rehberi" }
title field (analyzer: turkish):
"Elasticsearch Kurulum Rehberi"
↓ turkish analyzer
["elasticsearch", "kur", "rehber"]
↓
Inverted Index:
elasticsearch → doc1
kur → doc1
rehber → doc1
title.keyword field (no analyzer):
"Elasticsearch Kurulum Rehberi" → doc1Önemli: Index-time analysis sadece bir kez gerçekleşir — doküman index'lenirken. Token'lar inverted index'e yazıldıktan sonra orijinal metin _source'ta saklanır ama inverted index'teki token'lar artık değiştirilemez.
5.2 Search-Time Analysis
Bir arama yapıldığında, sorgu metni de analyze edilir — ama bu sefer search_analyzer kullanılır (tanımlanmadıysa analyzer kullanılır):
Sorgu: "Kurulum rehberleri"
search_analyzer (turkish):
"Kurulum rehberleri"
↓ turkish analyzer
["kur", "rehber"]
Inverted index'te arama:
"kur" → doc1 ✓
"rehber" → doc1 ✓
Sonuç: doc1 bulundu!"Kurulum" ve "Kurulumlar" aynı köke ("kur") indirgenir → ikisi de eşleşir.
5.3 Farklı Index ve Search Analyzer Kullanımı
Bazı senaryolarda index-time ve search-time'da farklı analyzer kullanmak gerekir:
PUT different_analyzers
{
"settings": {
"analysis": {
"filter": {
"edge_ngram_filter": {
"type": "edge_ngram",
"min_gram": 2,
"max_gram": 10
},
"synonym_filter": {
"type": "synonym_graph",
"synonyms": [
"telefon, mobil, cep telefonu",
"bilgisayar, laptop, pc"
]
}
},
"analyzer": {
"index_analyzer": {
"type": "custom",
"tokenizer": "standard",
"filter": ["lowercase", "edge_ngram_filter"]
},
"search_analyzer": {
"type": "custom",
"tokenizer": "standard",
"filter": ["lowercase", "synonym_filter"]
}
}
}
},
"mappings": {
"properties": {
"product_name": {
"type": "text",
"analyzer": "index_analyzer",
"search_analyzer": "search_analyzer"
}
}
}
}Bu tasarımda:
Index-time: Edge ngram ile prefix matching desteği
Search-time: Synonym ile eşanlamlı genişletme
Kullanıcı "mobil" aradığında, search analyzer bunu ["mobil", "telefon", "cep telefonu"]'na genişletir. Bu token'lar inverted index'teki edge ngram token'larıyla eşleşir.
5.4 term Query — Analyze Edilmez!
term query sorgu metnini analyze etmez — olduğu gibi inverted index'te arar:
// ❌ Bulamaz! Çünkü inverted index'te "Elasticsearch" küçük harf ("elasticsearch") olarak kayıtlı
GET my_index/_search
{
"query": {
"term": {
"title": "Elasticsearch"
}
}
}
// ✅ Küçük harfle yazın — inverted index'teki token ile eşleşir
GET my_index/_search
{
"query": {
"term": {
"title": "elasticsearch"
}
}
}
// ✅ Veya match query kullanın — otomatik analyze edilir
GET my_index/_search
{
"query": {
"match": {
"title": "Elasticsearch"
}
}
}Bu, text field'larla term query kullanmanın neden tehlikeli olduğunu gösterir. text + match veya keyword + term kombinasyonlarını tercih edin.
6. Gerçek Dünya Senaryosu: Blog Platformu
Bir blog platformu için kapsamlı multi-field mapping tasarımı:
PUT blog_platform
{
"settings": {
"analysis": {
"filter": {
"turkish_lowercase": {
"type": "lowercase",
"language": "turkish"
},
"turkish_stop": {
"type": "stop",
"stopwords": "_turkish_"
},
"turkish_stemmer": {
"type": "stemmer",
"language": "turkish"
},
"edge_ngram_filter": {
"type": "edge_ngram",
"min_gram": 2,
"max_gram": 10
}
},
"analyzer": {
"turkish_full": {
"type": "custom",
"tokenizer": "standard",
"filter": ["turkish_lowercase", "turkish_stop", "turkish_stemmer"]
},
"autocomplete_idx": {
"type": "custom",
"tokenizer": "standard",
"filter": ["turkish_lowercase", "edge_ngram_filter"]
},
"autocomplete_srch": {
"type": "custom",
"tokenizer": "standard",
"filter": ["turkish_lowercase"]
}
},
"normalizer": {
"lowercase_norm": {
"type": "custom",
"filter": ["lowercase"]
}
}
}
},
"mappings": {
"properties": {
"title": {
"type": "text",
"analyzer": "turkish_full",
"fields": {
"keyword": {
"type": "keyword"
},
"autocomplete": {
"type": "text",
"analyzer": "autocomplete_idx",
"search_analyzer": "autocomplete_srch"
},
"standard": {
"type": "text",
"analyzer": "standard"
}
}
},
"content": {
"type": "text",
"analyzer": "turkish_full",
"fields": {
"standard": {
"type": "text",
"analyzer": "standard"
}
}
},
"author": {
"type": "text",
"analyzer": "standard",
"fields": {
"keyword": {
"type": "keyword"
},
"autocomplete": {
"type": "text",
"analyzer": "autocomplete_idx",
"search_analyzer": "autocomplete_srch"
}
}
},
"tags": {
"type": "keyword",
"normalizer": "lowercase_norm"
},
"category": {
"type": "keyword"
},
"publish_date": {
"type": "date"
},
"view_count": {
"type": "integer"
},
"status": {
"type": "keyword"
}
}
}
}Veri Ekleme ve Sorgulama
// Veri ekle
POST blog_platform/_bulk
{"index":{"_id":"1"}}
{"title":"Elasticsearch ile Full-Text Arama","content":"Bu yazıda Elasticsearch'ün arama özelliklerini inceliyoruz. Full-text search modern uygulamaların vazgeçilmez bir parçasıdır.","author":"Ahmet Yılmaz","tags":["elasticsearch","arama","java"],"category":"Teknoloji","publish_date":"2024-01-15","view_count":1520,"status":"published"}
{"index":{"_id":"2"}}
{"title":"Spring Boot ve Elasticsearch Entegrasyonu","content":"Spring Data Elasticsearch ile Java uygulamalarınızda Elasticsearch kullanabilirsiniz. Repository pattern sayesinde CRUD işlemleri çok kolaydır.","author":"Mehmet Demir","tags":["spring-boot","elasticsearch","java"],"category":"Teknoloji","publish_date":"2024-02-20","view_count":2340,"status":"published"}
{"index":{"_id":"3"}}
{"title":"React ile Modern Web Geliştirme","content":"React kütüphanesi ile component-based web uygulamaları geliştirin. Hooks, context ve state management konularını ele alıyoruz.","author":"Ayşe Kaya","tags":["react","javascript","web"],"category":"Frontend","publish_date":"2024-03-10","view_count":3100,"status":"published"}
// 1. Full-text arama (Türkçe stemming)
GET blog_platform/_search
{
"query": {
"match": {
"title": "aramaları"
}
}
}
// "aramaları" → stemmer → "ara" → "Arama" içeren doküman bulunur
// 2. Autocomplete
GET blog_platform/_search
{
"query": {
"match": {
"title.autocomplete": "ela"
}
}
}
// "ela" → Elasticsearch içeren dokümanlar
// 3. Exact match (keyword)
GET blog_platform/_search
{
"query": {
"term": {
"title.keyword": "Elasticsearch ile Full-Text Arama"
}
}
}
// 4. Aggregation — En popüler kategoriler
GET blog_platform/_search
{
"size": 0,
"aggs": {
"categories": {
"terms": {
"field": "category",
"size": 10
}
},
"popular_tags": {
"terms": {
"field": "tags",
"size": 20
}
}
}
}
// 5. Sorting — Yayın tarihine göre sırala
GET blog_platform/_search
{
"sort": [
{ "publish_date": "desc" }
]
}
// 6. Multi-match — Birden fazla field'da ara
GET blog_platform/_search
{
"query": {
"multi_match": {
"query": "elasticsearch java",
"fields": [
"title^3",
"title.standard",
"content",
"tags^2"
],
"type": "best_fields"
}
}
}7. copy_to — Birden Fazla Field'ı Birleştirme
copy_to parametresi, birden fazla field'ın değerini tek bir "catch-all" field'a kopyalar:
PUT search_all_index
{
"mappings": {
"properties": {
"title": {
"type": "text",
"copy_to": "search_all"
},
"description": {
"type": "text",
"copy_to": "search_all"
},
"tags": {
"type": "keyword",
"copy_to": "search_all"
},
"search_all": {
"type": "text",
"analyzer": "turkish"
}
}
}
}Artık tek bir field'da tüm içeriği arayabilirsiniz:
GET search_all_index/_search
{
"query": {
"match": {
"search_all": "elasticsearch"
}
}
}`copy_to` özellikleri:
Kaynak field'ların değerleri
search_all'a kopyalanır (index-time)_source'tasearch_allgörünmez (fiziksel olarak saklanmaz)Birden fazla field aynı hedefe kopyalanabilir
Zincirleme kopya desteklenir (A → B → C)
⚠️ Dikkat: copy_to index boyutunu artırır çünkü aynı veri birden fazla kez index'lenir.
8. ignore_above Parametresi
keyword field'larda çok uzun string'lerin index'lenmesini engellemek için ignore_above kullanılır:
"title": {
"type": "text",
"fields": {
"keyword": {
"type": "keyword",
"ignore_above": 256
}
}
}256 karakterden uzun değerler keyword sub-field'da index'lenmez (ama _source'ta tam haliyle saklanır).
Neden önemli?
Keyword field'lar tek token olarak saklanır
Çok uzun keyword'ler gereksiz bellek tüketir
Aggregation'larda 10.000 karakterlik bir keyword anlamsızdır
Lucene'in term uzunluk limiti 32KB'dir
Değeri nasıl ayarlamalı?
| Alan Tipi | Önerilen ignore_above |
|---|---|
| E-posta | 254 |
| URL | 2048 |
| Ürün adı | 256 |
| Kategori | 128 |
| Ülke kodu | 3 |
9. enabled: false — Index'lemeyi Kapatma
Bazen bir field'ı saklamak ama index'lememek istersiniz:
PUT logs_index
{
"mappings": {
"properties": {
"message": {
"type": "text"
},
"raw_payload": {
"type": "object",
"enabled": false
}
}
}
}raw_payload _source'ta saklanır ama aranabilir değildir. Bu, index boyutunu küçültür ve index'leme hızını artırır.
10. Java ile Multi-field Mapping
import co.elastic.clients.elasticsearch.ElasticsearchClient;
import co.elastic.clients.elasticsearch._types.mapping.*;
public class MultiFieldMappingJava {
public static void createMultiFieldIndex(ElasticsearchClient client) throws Exception {
client.indices().create(c -> c
.index("products_multifield")
.settings(s -> s
.analysis(a -> a
.filter("tr_lowercase", f -> f
.definition(d -> d
.lowercase(l -> l.language("turkish"))
)
)
.filter("tr_stemmer", f -> f
.definition(d -> d
.stemmer(st -> st.language("turkish"))
)
)
.filter("edge_ngram_f", f -> f
.definition(d -> d
.edgeNGram(e -> e.minGram(2).maxGram(10))
)
)
.analyzer("turkish_custom", an -> an
.custom(cu -> cu
.tokenizer("standard")
.filter("tr_lowercase", "tr_stemmer")
)
)
.analyzer("autocomplete_i", an -> an
.custom(cu -> cu
.tokenizer("standard")
.filter("tr_lowercase", "edge_ngram_f")
)
)
.analyzer("autocomplete_s", an -> an
.custom(cu -> cu
.tokenizer("standard")
.filter("tr_lowercase")
)
)
)
)
.mappings(m -> m
.properties("product_name", p -> p
.text(t -> t
.analyzer("turkish_custom")
.fields("keyword", f -> f
.keyword(k -> k.ignoreAbove(256))
)
.fields("autocomplete", f -> f
.text(t2 -> t2
.analyzer("autocomplete_i")
.searchAnalyzer("autocomplete_s")
)
)
)
)
.properties("category", p -> p
.keyword(k -> k)
)
.properties("price", p -> p
.float_(fl -> fl)
)
)
);
System.out.println("Multi-field index oluşturuldu.");
}
public static void searchMultiField(ElasticsearchClient client) throws Exception {
// Full-text arama (Türkçe stemming)
var fullTextResponse = client.search(s -> s
.index("products_multifield")
.query(q -> q
.match(m -> m
.field("product_name")
.query("telefonlar")
)
),
Object.class
);
System.out.println("Full-text sonuç: " + fullTextResponse.hits().total().value());
// Autocomplete
var autocompleteResponse = client.search(s -> s
.index("products_multifield")
.query(q -> q
.match(m -> m
.field("product_name.autocomplete")
.query("sam")
)
),
Object.class
);
System.out.println("Autocomplete sonuç: " + autocompleteResponse.hits().total().value());
// Aggregation
var aggResponse = client.search(s -> s
.index("products_multifield")
.size(0)
.aggregations("categories", a -> a
.terms(t -> t
.field("category")
.size(10)
)
),
Object.class
);
System.out.println("Kategori sayısı: " +
aggResponse.aggregations().get("categories").sterms().buckets().array().size());
}
}11. Best Practices
✅ Yapın
| Uygulama | Neden |
|---|---|
| Her text field'a keyword sub-field ekleyin | Sorting ve aggregation için gerekli |
| Multi-field isimlendirmede tutarlı olun | title.keyword, title.autocomplete — her index'te aynı pattern |
ignore_above değerini field'a göre ayarlayın | Gereksiz index boyutu artışını önler |
| Autocomplete sub-field'ını sadece kısa alanlara ekleyin | Uzun açıklama alanlarında gereksiz |
copy_to ile catch-all field oluşturun | Tek field'da genel arama kolaylaşır |
❌ Yapmayın
| Uygulama | Neden |
|---|---|
| Her field'a 5+ sub-field eklemeyin | Index boyutu ve performans kaybı |
text field'a term query ile sorgulama yapmayın | Analyze edilmiş token'larla eşleşmez |
| keyword field'da full-text arama yapmayın | Match query keyword field'da exact match gibi çalışır |
| Dynamic mapping'e production'da güvenmeyin | Gereksiz field'lar oluşabilir |
12. Yaygın Hatalar
Hata 1: text + term Query
// ❌ "Samsung Galaxy" term olarak inverted index'te YOKTUR
GET my_index/_search
{
"query": {
"term": {
"product_name": "Samsung Galaxy"
}
}
}
// ✅ match query kullanın (analyze edilir) veya keyword sub-field kullanın
GET my_index/_search
{
"query": {
"match": {
"product_name": "Samsung Galaxy"
}
}
}
// VEYA
GET my_index/_search
{
"query": {
"term": {
"product_name.keyword": "Samsung Galaxy S24 Ultra"
}
}
}Hata 2: keyword Field'da Aggregation Yerine text Field
// ❌ text field'da aggregation — her token ayrı bucket olur
GET my_index/_search
{
"size": 0,
"aggs": {
"products": {
"terms": {
"field": "product_name" // text field!
}
}
}
}
// Sonuç: "samsung", "galaxy", "s24" ayrı ayrı bucket olarak gelir
// ✅ keyword sub-field kullanın
GET my_index/_search
{
"size": 0,
"aggs": {
"products": {
"terms": {
"field": "product_name.keyword" // keyword sub-field
}
}
}
}
// Sonuç: "Samsung Galaxy S24 Ultra" tek bucket olarak gelirHata 3: Mapping'i Sonradan Değiştirmeye Çalışmak
// ❌ Mevcut field'a sub-field eklenemez (varolan dokümanlar etkilenmez)
// Ama aslında Elasticsearch buna izin verir — yeni sub-field ekleme mümkündür!
PUT my_index/_mapping
{
"properties": {
"title": {
"type": "text",
"fields": {
"keyword": { "type": "keyword" },
"new_subfield": { "type": "text", "analyzer": "turkish" }
}
}
}
}
// ✅ Bu çalışır! Ama mevcut dokümanlar yeni sub-field'da index'lenmemiştir.
// Mevcut dokümanlar için _update_by_query gerekir:
POST my_index/_update_by_query?conflicts=proceed13. Performans Etkileri
| Multi-field Sayısı | Index Boyutu | Index Hızı | Arama Esnekliği |
|---|---|---|---|
| 1 (sadece text) | 1x | Hızlı | Düşük |
| 2 (text + keyword) | 1.3-1.5x | Normal | Orta |
| 3 (text + keyword + autocomplete) | 2-3x | Yavaş | Yüksek |
| 4+ | 3-5x+ | Çok yavaş | Çok yüksek |
Kural: Her ek sub-field index boyutunu ve index'leme süresini artırır. Sadece gerçekten ihtiyaç duyduğunuz sub-field'ları ekleyin.
Index Boyutunu Kontrol Etme
// Index boyutunu görme
GET my_index/_stats/store
// Field bazlı disk kullanımı (8.x+)
GET my_index/_disk_usage?run_expensive_tasks=trueÖzet
Multi-field mapping, aynı alanı farklı amaçlar için birden fazla şekilde index'lemenizi sağlar
En yaygın pattern text + keyword: full-text arama + aggregation/sorting/exact match
Index-time analysis doküman yazılırken, search-time analysis sorgu yapılırken gerçekleşir — farklı analyzer'lar kullanılabilir
termquery sorgu metnini analyze etmez — text field'larla dikkatli kullanın`copy_to` birden fazla field'ı tek bir aranabilir alana birleştirir
`ignore_above` keyword field'larda çok uzun değerlerin index'lenmesini engeller
Dynamic mapping otomatik text + keyword multi-field oluşturur — ama production'da explicit mapping tercih edin
Her ek sub-field index boyutunu artırır — sadece ihtiyaç duyulanları ekleyin
AI Asistan
Sorularını yanıtlamaya hazır