Tüm Field Tipleri Derinlemesine
Giriş — Doğru Kutuya Doğru Eşya
Bir depo düşünün. Kitaplar için raf, sıvılar için bidon, kıyafetler için askı kullanırsınız. Her eşyayı aynı kutuya atarsanız sonra ne bulabilirsiniz ne de düzenleyebilirsiniz. Elasticsearch'te de her veri parçasını doğru field type ile saklamak bu kadar kritiktir.
Yanlış field tipi seçimi genellikle hemen fark edilmez — çünkü Elasticsearch dynamic mapping ile bir şekilde çalışır. Ama sonuçları ağırdır: gereksiz disk kullanımı, yavaş aramalar, aggregation'ların çalışmaması veya hassasiyet kaybı. Bu ders, Elasticsearch'teki tüm field tiplerini birer birer, ne zaman kullanılacağı, kısıtlamaları ve pratik örnekleriyle inceleyecek.
1. String Tipler: text ve keyword
1.1 text
text tipi, full-text search için optimize edilmiş string tipidir. Değer bir analyzer'dan geçirilir ve tokenize edilir.
PUT /articles
{
"mappings": {
"properties": {
"title": {
"type": "text",
"analyzer": "standard",
"search_analyzer": "standard",
"index_options": "positions",
"norms": true
}
}
}
}text parametreleri:
| Parametre | Varsayılan | Açıklama |
|---|---|---|
analyzer | standard | Index-time analyzer |
search_analyzer | analyzer değeri | Search-time analyzer (farklı olabilir) |
index | true | Index'lensin mi? |
index_options | positions | docs, freqs, positions, offsets |
norms | true | Length normalization skoru. Sadece scoring gerekliyse açık tutun |
store | false | Ayrı sakla (normalde _source'tan okunur) |
term_vector | no | yes, with_positions, with_offsets, with_positions_offsets |
fielddata | false | Aggregation/sort için memory-based yapı (⚠️ dikkat!) |
eager_global_ordinals | false | Global ordinals'ı hemen oluştur |
similarity | BM25 | Scoring algoritması |
// text field'ında arama
GET /articles/_search
{
"query": {
"match": {
"title": "elasticsearch performans optimizasyonu"
}
}
}⚠️ Dikkat:
textfield'ları üzerinde aggregation veya sorting yapılamaz (fielddata açılmadıkça). Hem arama hem aggregation istiyorsanız multi-field kullanın.
1.2 keyword
keyword tipi, tokenize edilmeyen string tipidir. Tam değer olarak saklanır ve exact match, aggregation, sorting için kullanılır.
PUT /products
{
"mappings": {
"properties": {
"status": {
"type": "keyword",
"ignore_above": 256,
"normalizer": "lowercase_normalizer"
}
}
},
"settings": {
"analysis": {
"normalizer": {
"lowercase_normalizer": {
"type": "custom",
"filter": ["lowercase"]
}
}
}
}
}keyword parametreleri:
| Parametre | Varsayılan | Açıklama |
|---|---|---|
ignore_above | 2147483647 | Bu uzunluktan büyük değerler index'lenmez |
normalizer | null | Tokenize etmeden karakter dönüşümü (lowercase gibi) |
doc_values | true | Aggregation/sort için columnar yapı |
index | true | Index'lensin mi? |
null_value | null | null değer yerine kullanılacak değer |
eager_global_ordinals | false | Terms aggregation performansı için |
// keyword field'ında exact match
GET /products/_search
{
"query": { "term": { "status": "active" } }
}
// keyword field'ında aggregation
GET /products/_search
{
"size": 0,
"aggs": {
"statuses": { "terms": { "field": "status" } }
}
}1.3 text + keyword Multi-Field Pattern
En yaygın kullanım — hem arama hem aggregation:
PUT /products
{
"mappings": {
"properties": {
"name": {
"type": "text",
"analyzer": "standard",
"fields": {
"keyword": {
"type": "keyword",
"ignore_above": 256
},
"autocomplete": {
"type": "text",
"analyzer": "edge_ngram_analyzer"
}
}
}
}
}
}name → text (full-text search)
name.keyword → keyword (aggregation, sorting, exact match)
name.autocomplete → text + edge_ngram (autocomplete)💡 İpucu:
ignore_above: 256dynamic mapping'in varsayılanıdır. Eğer keyword alanınız uzun URL'ler veya açıklamalar içerecekse bu değeri artırın. Index'lenmeyen değerler aggregation'larda görünmez.
2. Sayısal Tipler
2.1 integer, long, short, byte
PUT /metrics
{
"mappings": {
"properties": {
"count": { "type": "integer" },
"total_bytes": { "type": "long" },
"port": { "type": "short" },
"priority": { "type": "byte" }
}
}
}Sayısal tipler ve aralıkları:
┌──────────┬────────────────────────────┬──────────────┐
│ Tip │ Aralık │ Boyut │
├──────────┼────────────────────────────┼──────────────┤
│ byte │ -128 ~ 127 │ 8-bit │
│ short │ -32,768 ~ 32,767 │ 16-bit │
│ integer │ -2^31 ~ 2^31 - 1 │ 32-bit │
│ long │ -2^63 ~ 2^63 - 1 │ 64-bit │
└──────────┴────────────────────────────┴──────────────┘Ne zaman hangisi?
byte: 0-255 arası değerler (HTTP status category, priority level)short: Port numaraları, küçük sayaçlarinteger: Çoğu sayısal alan için varsayılan seçimlong: Büyük sayılar (Unix timestamp millis, büyük ID'ler, file size byte)
💡 İpucu: Elasticsearch dahili olarak tüm sayısal tipleri BKD tree (Block KD-Tree) yapısında saklar. Daha küçük tip seçmek disk'te az yer kaplar ama arama hızını doğrudan etkilemez. Yine de doğru tipi seçmek iyi bir pratiktir.
2.2 float, double, half_float
PUT /products
{
"mappings": {
"properties": {
"price": { "type": "float" },
"precise_measurement": { "type": "double" },
"score": { "type": "half_float" }
}
}
}┌─────────────┬────────────────────────┬──────────┐
│ Tip │ Hassasiyet │ Boyut │
├─────────────┼────────────────────────┼──────────┤
│ half_float │ ~3 ondalık basamak │ 16-bit │
│ float │ ~7 ondalık basamak │ 32-bit │
│ double │ ~15 ondalık basamak │ 64-bit │
└─────────────┴────────────────────────┴──────────┘⚠️ Dikkat: Floating point hassasiyet kaybı!
floattipi0.1 + 0.2'yi tam0.3olarak saklayamaz. Finansal veriler içinscaled_floatkullanın.
2.3 scaled_float — Finansal Veriler İçin
scaled_float, ondalıklı sayıları dahili olarak long olarak saklar. scaling_factor ile çarpılır ve tam sayıya dönüştürülür:
PUT /orders
{
"mappings": {
"properties": {
"price": {
"type": "scaled_float",
"scaling_factor": 100
},
"tax_rate": {
"type": "scaled_float",
"scaling_factor": 10000
}
}
}
}price: 29.99 → dahili olarak 2999 (long) saklanır
tax_rate: 0.1875 → dahili olarak 1875 (long) saklanırAvantajları:
Hassasiyet kaybı yok (long arithmetic)
float'tan daha az disk kullanır (long sıkıştırması daha verimli)Aggregation'lar daha hızlı
Ne zaman kullanılmalı: Fiyat, vergi oranı, oran, yüzde gibi sabit ondalık hassasiyetli değerler.
3. boolean
PUT /users
{
"mappings": {
"properties": {
"is_active": { "type": "boolean" }
}
}
}Kabul edilen değerler:
true değerleri: true, "true", "yes", "on", "1", 1
false değerleri: false, "false", "no", "off", "0", 0, "" (boş string)// Bunların hepsi aynı
POST /users/_doc/1 { "is_active": true }
POST /users/_doc/2 { "is_active": "true" }
POST /users/_doc/3 { "is_active": "yes" }
// Term query ile arama
GET /users/_search
{
"query": { "term": { "is_active": true } }
}⚠️ Dikkat: Boolean field'lar dahili olarak
"T"ve"F"keyword olarak saklanır. Aggregation'lardatrue/falseyerine"T"/"F"görebilirsiniz (client'a bağlı).
4. Date Tipleri: date ve date_nanos
4.1 date
PUT /events
{
"mappings": {
"properties": {
"created_at": {
"type": "date",
"format": "yyyy-MM-dd'T'HH:mm:ss.SSSZ||yyyy-MM-dd||epoch_millis"
}
}
}
}Dahili saklama: Tüm date değerleri dahili olarak epoch milliseconds (long) olarak saklanır. Format sadece parsing ve görüntüleme içindir.
Desteklenen formatlar:
// Hepsi geçerli date değerleri:
"2024-02-27T10:30:00.000Z" // ISO 8601
"2024-02-27T10:30:00+03:00" // Timezone offset ile
"2024-02-27" // Sadece tarih
1709029800000 // Epoch millis
"1709029800000" // Epoch millis (string)Yaygın format pattern'ları:
yyyy-MM-dd → 2024-02-27
yyyy-MM-dd'T'HH:mm:ss → 2024-02-27T10:30:00
yyyy-MM-dd'T'HH:mm:ss.SSSZ → 2024-02-27T10:30:00.000+0300
strict_date_optional_time → ISO 8601 (varsayılan)
epoch_millis → 1709029800000
epoch_second → 1709029800
date_hour_minute_second → 2024-02-27T10:30:00
basic_date_time_no_millis → 20240227T103000+0300// Birden fazla format (|| ile ayırma)
"format": "yyyy-MM-dd'T'HH:mm:ss.SSSZ||yyyy-MM-dd||epoch_millis"4.2 date_nanos
Nanosaniye hassasiyeti gerektiren durumlar için:
PUT /high-precision-events
{
"mappings": {
"properties": {
"timestamp": {
"type": "date_nanos"
}
}
}
}
// Nanosaniye hassasiyetinde değer
POST /high-precision-events/_doc/1
{
"timestamp": "2024-02-27T10:30:00.123456789Z"
}date vs date_nanos:
date: milisaniye hassasiyeti → 2024-02-27T10:30:00.123Z
date_nanos: nanosaniye hassasiyeti → 2024-02-27T10:30:00.123456789Z
date: epoch_millis (long) → 13 haneli sayı
date_nanos: epoch_nanos (long) → 19 haneli sayı⚠️ Dikkat:
date_nanoskullandığınızda aggregation ve sorting'de milisaniye hassasiyeti kaybedilmez ama bazı aggregation'lar (date_histogram gibi) nanosaniye hassasiyetini göstermeyebilir. Ayrıcadate_nanos'un aralığıdate'ten dardır: 1970-2262 arası (long overflow nedeniyle).
5. ip — IP Adresi Tipi
PUT /access-logs
{
"mappings": {
"properties": {
"client_ip": { "type": "ip" }
}
}
}
// IPv4 ve IPv6 desteği
POST /access-logs/_doc/1 { "client_ip": "192.168.1.100" }
POST /access-logs/_doc/2 { "client_ip": "::ffff:192.168.1.100" }
POST /access-logs/_doc/3 { "client_ip": "2001:0db8:85a3:0000:0000:8a2e:0370:7334" }CIDR notation ile arama:
GET /access-logs/_search
{
"query": {
"term": { "client_ip": "192.168.1.0/24" }
}
}
// Range query
GET /access-logs/_search
{
"query": {
"range": {
"client_ip": {
"gte": "192.168.1.0",
"lte": "192.168.1.255"
}
}
}
}💡 İpucu: IP field'ı dahili olarak 128-bit integer olarak saklanır. IPv4 adresleri IPv6-mapped adrese dönüştürülür (
::ffff:192.168.1.100). Bu sayede IPv4 ve IPv6 aynı field'da karışık saklanabilir.
6. Geo Tipleri: geo_point ve geo_shape
6.1 geo_point
Yeryüzünde bir nokta (enlem/boylam):
PUT /restaurants
{
"mappings": {
"properties": {
"location": { "type": "geo_point" }
}
}
}
// Farklı geo_point formatları
POST /restaurants/_doc/1 { "location": { "lat": 41.0082, "lon": 28.9784 } }
POST /restaurants/_doc/2 { "location": "41.0082,28.9784" }
POST /restaurants/_doc/3 { "location": [28.9784, 41.0082] } // ⚠️ [lon, lat] sırası!
POST /restaurants/_doc/4 { "location": "u14dg9s0" } // Geohash⚠️ Dikkat: Array formatında sıra
[longitude, latitude]'dir — GeoJSON standardına uygun. Ama object formatında{"lat": ..., "lon": ...}. Bu tutarsızlık yaygın bir hata kaynağıdır!
6.2 geo_shape
Nokta, çizgi, polygon gibi karmaşık coğrafi şekiller:
PUT /areas
{
"mappings": {
"properties": {
"boundary": { "type": "geo_shape" }
}
}
}
// Polygon tanımlama
POST /areas/_doc/1
{
"boundary": {
"type": "polygon",
"coordinates": [
[[28.5, 40.8], [29.5, 40.8], [29.5, 41.3], [28.5, 41.3], [28.5, 40.8]]
]
}
}
// Point (geo_shape olarak)
POST /areas/_doc/2
{
"boundary": {
"type": "point",
"coordinates": [28.9784, 41.0082]
}
}
// Circle
POST /areas/_doc/3
{
"boundary": {
"type": "circle",
"coordinates": [28.9784, 41.0082],
"radius": "5km"
}
}Desteklenen şekiller: point, linestring, polygon, multipoint, multilinestring, multipolygon, geometrycollection, envelope (bounding box), circle
7. completion — Autocomplete İçin
completion tipi, suggest özelliği (autocomplete) için özel olarak optimize edilmiş bir field tipidir. FST (Finite State Transducer) veri yapısını kullanır ve tamamen bellekte çalışır.
PUT /products
{
"mappings": {
"properties": {
"suggest": {
"type": "completion",
"analyzer": "simple",
"search_analyzer": "simple",
"preserve_separators": true,
"preserve_position_increments": true,
"max_input_length": 50
}
}
}
}
// Doküman indexleme — input ve weight ile
POST /products/_doc/1
{
"suggest": {
"input": ["iPhone 15 Pro", "Apple iPhone 15", "iPhone"],
"weight": 100
}
}
POST /products/_doc/2
{
"suggest": {
"input": ["Samsung Galaxy S24", "Galaxy S24", "Samsung"],
"weight": 80
}
}
// Suggest query
GET /products/_search
{
"suggest": {
"product-suggest": {
"prefix": "iph",
"completion": {
"field": "suggest",
"size": 5,
"fuzzy": {
"fuzziness": 1
}
}
}
}
}Parametreler:
preserve_separators:true→ "foo bar" ve "foobar" farklı;false→ aynıpreserve_position_increments: Stop word'ler sonrası pozisyon korunmasımax_input_length: Input string uzunluk limiti (varsayılan 50)
💡 İpucu:
completiontipi in-memory FST kullandığı için çok hızlıdır (sub-millisecond). Ama çok fazla input varsa bellek tüketimi artar. Milyonlarca ürün için dikkatli capacity planning yapın.
8. dense_vector ve sparse_vector — ML ve Vektör Arama
8.1 dense_vector
Makine öğrenmesi embedding'leri ve kNN (k-Nearest Neighbors) arama için:
PUT /embeddings
{
"mappings": {
"properties": {
"title_vector": {
"type": "dense_vector",
"dims": 384,
"index": true,
"similarity": "cosine"
}
}
}
}
// Vektör ile doküman indexleme
POST /embeddings/_doc/1
{
"title": "Elasticsearch tutorial",
"title_vector": [0.12, -0.34, 0.56, ...] // 384 boyutlu vektör
}
// kNN search
GET /embeddings/_search
{
"knn": {
"field": "title_vector",
"query_vector": [0.11, -0.33, 0.55, ...],
"k": 10,
"num_candidates": 100
}
}dense_vector parametreleri:
dims: Vektör boyutu (1-4096 arası, 8.x'te artırıldı)index:trueolursa HNSW index oluşturulur (kNN arama için)similarity:cosine,dot_product,l2_norm,max_inner_productindex_options.type:hnsw(varsayılan) veyaflatindex_options.m: HNSW graph bağlantı sayısı (varsayılan 16)index_options.ef_construction: Index oluşturma kalitesi (varsayılan 100)
8.2 sparse_vector
Seyrek vektörler (çoğu eleman 0 olan) için:
PUT /sparse-search
{
"mappings": {
"properties": {
"ml_tokens": {
"type": "sparse_vector"
}
}
}
}
// Sparse vektör — sadece non-zero değerler
POST /sparse-search/_doc/1
{
"ml_tokens": {
"elasticsearch": 2.5,
"search": 1.8,
"engine": 1.2,
"tutorial": 0.9
}
}Sparse vector genellikle ELSER (Elastic Learned Sparse EncodeR) veya benzeri modellerin çıktıları için kullanılır.
9. flattened — Yapısı Bilinmeyen JSON
flattened tipi, iç yapısı önceden bilinmeyen veya çok değişken JSON objeleri için idealdir. Tüm alt alanları tek bir field altında keyword olarak index'ler:
PUT /events
{
"mappings": {
"properties": {
"metadata": {
"type": "flattened",
"depth_limit": 20,
"ignore_above": 256,
"doc_values": true
}
}
}
}
// Rastgele yapıda metadata
POST /events/_doc/1
{
"metadata": {
"user": { "name": "Ali", "role": "admin" },
"action": "login",
"details": {
"browser": "Chrome",
"os": "Windows",
"version": "120.0"
}
}
}
// Arama — tüm alt alanlar keyword olarak aranır
GET /events/_search
{
"query": {
"term": { "metadata": "Chrome" }
}
}
// Veya alt alan belirterek
GET /events/_search
{
"query": {
"term": { "metadata.details.browser": "Chrome" }
}
}Ne zaman kullanılmalı:
Label'lar, tag'ler, metadata gibi yapısı dinamik olan alanlar
Her dokümanın farklı field'lara sahip olabileceği durumlar
Mapping explosion'ı önlemek istediğinizde
Kısıtlamalar:
Tüm değerler keyword olarak saklanır — full-text search yok
Sayısal range query çalışmaz (hepsi string)
Nested aggregation yok
⚠️ Dikkat:
flattenedtip bir kaçış yoludur ama trade-off'ları önemlidir. Eğer o alanlar üzerinde full-text search veya sayısal range query yapmanız gerekecekse,flattenedyerine düzgün mapping tanımlayın.
10. join — Parent-Child İlişkileri
join tipi, aynı index içinde parent-child ilişkisi kurar:
PUT /qa-forum
{
"mappings": {
"properties": {
"relation": {
"type": "join",
"relations": {
"question": "answer"
}
},
"title": { "type": "text" },
"body": { "type": "text" },
"author": { "type": "keyword" }
}
}
}
// Parent doküman (question)
POST /qa-forum/_doc/1?routing=1
{
"title": "Elasticsearch'te geo search nasıl yapılır?",
"body": "Geo point kullanmak istiyorum...",
"author": "ali",
"relation": { "name": "question" }
}
// Child doküman (answer)
POST /qa-forum/_doc/2?routing=1
{
"body": "geo_point tipini kullanarak geo_distance query yapabilirsiniz.",
"author": "ayse",
"relation": {
"name": "answer",
"parent": "1"
}
}
// Parent'a göre child'ları bul
GET /qa-forum/_search
{
"query": {
"has_parent": {
"parent_type": "question",
"query": {
"match": { "title": "geo search" }
}
}
}
}⚠️ Dikkat:
jointipi performans açısından pahalıdır. Parent ve child dokümanları aynı shard'da olmalıdır (routing zorunlu). Mümkünsenestedtipi tercih edin —joinsadece parent-child ilişkisinin gerçekten bağımsız dokümanlar olması gerektiğinde kullanılmalıdır.
11. alias — Field Alias
Mevcut bir field'a alternatif isim verir:
PUT /products
{
"mappings": {
"properties": {
"product_name": { "type": "text" },
"name": {
"type": "alias",
"path": "product_name"
}
}
}
}
// Her iki isim de çalışır
GET /products/_search { "query": { "match": { "name": "laptop" } } }
GET /products/_search { "query": { "match": { "product_name": "laptop" } } }Ne zaman kullanılmalı:
Field ismi değiştirilmek isteniyor ama reindex yapılamıyor
Farklı sistemlerin farklı field isimleri beklediği durumlar
12. binary — Base64 Encoded Veri
PUT /attachments
{
"mappings": {
"properties": {
"content": {
"type": "binary",
"doc_values": false,
"store": true
}
}
}
}
// Base64 encoded veri
POST /attachments/_doc/1
{
"content": "U29tZSBiaW5hcnkgZGF0YQ=="
}Kısıtlamalar:
Aranamaz — index'lenmez
Aggregation yapılamaz — doc_values yok
Sadece saklama amaçlı
Base64 encode zorunlu
13. rank_feature ve rank_features
Scoring'de boost olarak kullanılacak sayısal değerler için:
PUT /websites
{
"mappings": {
"properties": {
"pagerank": { "type": "rank_feature" },
"url_length": {
"type": "rank_feature",
"positive_score_impact": false
},
"topics": { "type": "rank_features" }
}
}
}
POST /websites/_doc/1
{
"pagerank": 8.5,
"url_length": 120,
"topics": {
"technology": 50,
"elasticsearch": 90,
"java": 30
}
}
// rank_feature query
GET /websites/_search
{
"query": {
"bool": {
"must": [
{ "match": { "content": "elasticsearch" } }
],
"should": [
{ "rank_feature": { "field": "pagerank", "boost": 2 } },
{ "rank_feature": { "field": "topics.elasticsearch" } }
]
}
}
}positive_score_impact: true(varsayılan): Değer arttıkça score artar (pagerank)positive_score_impact: false: Değer arttıkça score azalır (url_length — kısa URL daha iyi)rank_features: Birden fazla feature'ı map olarak saklar
14. Range Tipleri
Tek bir değer yerine aralık saklamak için:
PUT /events
{
"mappings": {
"properties": {
"time_range": { "type": "date_range" },
"age_range": { "type": "integer_range" },
"price_range": { "type": "float_range" },
"ip_range": { "type": "ip_range" }
}
}
}
POST /events/_doc/1
{
"time_range": {
"gte": "2024-02-27T09:00:00Z",
"lte": "2024-02-27T18:00:00Z"
},
"age_range": { "gte": 18, "lte": 65 },
"price_range": { "gte": 10.5, "lt": 99.99 },
"ip_range": { "gte": "192.168.1.0", "lte": "192.168.1.255" }
}
// Range ile kesişim araması
GET /events/_search
{
"query": {
"range": {
"time_range": {
"gte": "2024-02-27T12:00:00Z",
"lte": "2024-02-27T14:00:00Z",
"relation": "intersects"
}
}
}
}relation parametreleri:
intersects(varsayılan): Aralıklar kesişiyor mu?contains: Kayıtlı aralık, sorgu aralığını kapsıyor mu?within: Kayıtlı aralık, sorgu aralığının içinde mi?
15. Java ile Field Tipleri
15.1 Mapping Oluşturma
public class MappingManager {
private final ElasticsearchClient client;
public MappingManager(ElasticsearchClient client) {
this.client = client;
}
public void createComprehensiveMapping() throws IOException {
CreateIndexRequest request = CreateIndexRequest.of(c -> c
.index("comprehensive-index")
.mappings(m -> m
// String tipler
.properties("title", p -> p.text(t -> t
.analyzer("standard")
.fields("keyword", f -> f.keyword(k -> k.ignoreAbove(256)))
))
.properties("status", p -> p.keyword(k -> k))
// Sayısal tipler
.properties("count", p -> p.integer(i -> i))
.properties("total_bytes", p -> p.long_(l -> l))
.properties("price", p -> p.scaledFloat(sf -> sf.scalingFactor(100.0)))
// Boolean
.properties("is_active", p -> p.boolean_(b -> b))
// Date
.properties("created_at", p -> p.date(d -> d
.format("yyyy-MM-dd'T'HH:mm:ss.SSSZ||epoch_millis")
))
// IP
.properties("client_ip", p -> p.ip(ip -> ip))
// Geo
.properties("location", p -> p.geoPoint(g -> g))
// Completion
.properties("suggest", p -> p.completion(comp -> comp
.analyzer("simple")
))
// Flattened
.properties("metadata", p -> p.flattened(fl -> fl
.depthLimit(10)
))
// Dense vector
.properties("embedding", p -> p.denseVector(dv -> dv
.dims(384)
.index(true)
.similarity("cosine")
))
)
);
client.indices().create(request);
System.out.println("Comprehensive index created");
}
}15.2 Field Tipine Göre Doküman Oluşturma
public void indexDocument() throws IOException {
Map<String, Object> doc = new HashMap<>();
// String
doc.put("title", "Elasticsearch Deep Dive");
doc.put("status", "published");
// Number
doc.put("count", 42);
doc.put("total_bytes", 1073741824L);
doc.put("price", 29.99);
// Boolean
doc.put("is_active", true);
// Date
doc.put("created_at", "2024-02-27T10:30:00.000Z");
// IP
doc.put("client_ip", "192.168.1.100");
// Geo point
Map<String, Double> location = new HashMap<>();
location.put("lat", 41.0082);
location.put("lon", 28.9784);
doc.put("location", location);
// Completion suggest
Map<String, Object> suggest = new HashMap<>();
suggest.put("input", List.of("Elasticsearch Deep Dive", "ES Deep Dive"));
suggest.put("weight", 100);
doc.put("suggest", suggest);
// Flattened metadata
Map<String, Object> metadata = new HashMap<>();
metadata.put("source", "web");
metadata.put("campaign", "spring-2024");
doc.put("metadata", metadata);
IndexResponse response = client.index(i -> i
.index("comprehensive-index")
.document(doc)
);
System.out.println("Indexed: " + response.id());
}16. Tip Seçimi Karar Tablosu
┌──────────────────────────┬─────────────────┬──────────────────────────────────┐
│ Veri Türü │ Önerilen Tip │ Not │
├──────────────────────────┼─────────────────┼──────────────────────────────────┤
│ Tam metin (arama) │ text │ Analyzer seçimi kritik │
│ Sabit değer (enum, tag) │ keyword │ ignore_above ayarla │
│ İkisi birden │ text + keyword │ Multi-field kullan │
│ Tamsayı (küçük) │ integer │ Aralığa dikkat │
│ Tamsayı (büyük/ID) │ long │ Timestamp, büyük ID │
│ Ondalıklı (genel) │ float │ Hassasiyet kaybı olabilir │
│ Ondalıklı (finansal) │ scaled_float │ scaling_factor zorunlu │
│ Ondalıklı (bilimsel) │ double │ Gerçekten gerekli olmalı │
│ Doğru/Yanlış │ boolean │ Çeşitli string kabul eder │
│ Tarih/Zaman │ date │ Format tanımla │
│ Tarih (nanosaniye) │ date_nanos │ 1970-2262 aralığı │
│ IP adresi │ ip │ IPv4 + IPv6, CIDR desteği │
│ Konum (nokta) │ geo_point │ Array: [lon,lat] sırası! │
│ Konum (şekil) │ geo_shape │ Polygon, circle vb. │
│ Autocomplete │ completion │ In-memory FST, weight desteği │
│ ML embedding │ dense_vector │ kNN search için index:true │
│ Sparse embedding │ sparse_vector │ ELSER çıktıları │
│ Dinamik JSON │ flattened │ Sadece keyword arama │
│ Parent-child │ join │ Routing zorunlu, yavaş │
│ Alan takma adı │ alias │ Reindex gerektirmez │
│ İkili veri │ binary │ Base64, aranamaz │
│ Scoring boost │ rank_feature │ BM25 ile birleşir │
│ Aralık değer │ integer_range │ date_range, ip_range vb. │
└──────────────────────────┴─────────────────┴──────────────────────────────────┘17. Yaygın Hatalar
Hata 1: text field'ında aggregation yapmaya çalışmak
// ❌ Hata verir
GET /products/_search
{
"aggs": { "names": { "terms": { "field": "name" } } }
}
// "Text fields are not optimised for operations that require per-document field data"
// ✅ Doğru — .keyword sub-field kullan
GET /products/_search
{
"aggs": { "names": { "terms": { "field": "name.keyword" } } }
}Hata 2: geo_point array sırasını karıştırmak
// ❌ Lat/Lon ters! Object'te lat/lon, array'de lon/lat
{ "location": [41.0082, 28.9784] } // YANLIŞ — lat,lon
// ✅ Array: [longitude, latitude]
{ "location": [28.9784, 41.0082] } // DOĞRU — lon,latHata 3: float ile finansal veri saklamak
// ❌ Hassasiyet kaybı
{ "price": { "type": "float" } }
// 19.99 → dahili olarak 19.989999... olabilir
// ✅ scaled_float kullan
{ "price": { "type": "scaled_float", "scaling_factor": 100 } }18. Özet
text full-text search için, keyword exact match/aggregation/sort için kullanılır. Çoğu string alanında multi-field (text + keyword) pattern en iyisidir
Sayısal tiplerde scaled_float finansal veriler için altın standarttır —
float/double'ın hassasiyet kaybı riskini ortadan kaldırırdate tipi dahili olarak epoch millis saklar, format sadece parsing içindir. Birden fazla format
||ile desteklenirgeo_point array formatında
[lon, lat]sırası kullanır (GeoJSON standardı) — en yaygın hatalardan biri bu sıralamanın karıştırılmasıdırcompletion tipi autocomplete için in-memory FST kullanır ve sub-millisecond hızda çalışır
dense_vector makine öğrenmesi ve semantic search için kullanılır.
similarityparametresi (cosine, dot_product, l2_norm) use-case'e göre seçilmelidirflattened tipi yapısı değişken JSON verileri için mapping explosion'ı önler ama sadece keyword-level arama sunar
join tipi parent-child ilişkileri için vardır ama performans maliyeti yüksektir — mümkünse
nestedveya denormalizasyon tercih edin
AI Asistan
Sorularını yanıtlamaya hazır