Memahami mapping: dynamic vs explicit, parameter mapping seperti analyzer dan index; tipe data inti (text vs keyword, numerik, date, boolean, range); serta tipe kompleks (object, nested, geo, IP, join) dengan risiko mapping explosion.

Di episode 4 kalian membuat index dengan mapping sederhana. Sekarang kita bedah mapping secara menyeluruh — karena mapping adalah keputusan desain paling penting dalam Elasticsearch. Kesalahan memilih tipe data tidak bisa diperbaiki dengan mudah: field yang sudah terlanjur text harus di-reindex untuk diubah jadi keyword.
Episode 5 membahas: konsep dynamic vs explicit mapping, parameter-parameter mapping yang mengatur perilaku field, tipe data inti (text, keyword, numerik, date, boolean, binary, range), dan tipe kompleks (object, nested, array, geo, IP, join) — plus bahaya mapping explosion yang harus kalian hindari sejak awal.
Dynamic mapping membuat Elasticsearch menebak tipe dari nilai pertama yang masuk. String dengan teks panjang menjadi text; string pendek seperti kode atau status menjadi text + keyword sub-field. Menebak ini nyaman tapi sering salah sasaran. Aturan praktisnya:
"dynamic": "strict" agar field tak dikenal ditolak, bukan disimpulkan.{
"mappings": {
"dynamic": "strict",
"properties": {
"name": { "type": "text" },
"status": { "type": "keyword" }
}
}
}| Parameter | Fungsi |
|---|---|
index | Apakah field bisa dicari. false berarti tersimpan tapi tidak dicari — hemat resource |
analyzer | Analyzer yang dipakai saat indexing dan pencarian text |
doc_values | Struktur kolom untuk aggregation/sorting. Nonaktifkan jika tidak butuh agregasi |
store | Apakah nilai field disimpan terpisah dari _source |
coerce | Apakah nilai otomatis dikonversi (misal string "5" ke integer) |
ignore_above | Mengabaikan string lebih panjang dari nilai ini pada field keyword |
null_value | Nilai pengganti saat field bernilai null |
Perhatikan index: false: field ini masih bisa dibaca dari _source, tapi tidak bisa di-query. Parameter ini hemat disk dan mempercepat indexing untuk field yang tidak pernah dicari.
GET /produk/_mappingJika field tidak sengaja ter-create dengan tipe salah, opsi perbaikannya terbatas — tidak ada ALTER TABLE seperti SQL. Pilihannya: hapus dan buat ulang index, atau reindex (episode 13). Itulah mengapa menulis mapping dengan benar sejak awal sangat penting.
Ini perbedaan paling krusial di Elasticsearch:
text — dipecah oleh analyzer menjadi token (kata), lalu diindeks untuk full-text search. Mencari "kaos polos" bisa mencocokkan dokumen dengan field "name": "Kaos Polos Premium". Support partial matching, relevansi, dan stemming.keyword — disimpan sebagai satu nilai utuh, tidak dianalisis. Hanya cocok untuk exact match, sorting, dan aggregation. Cocok untuk status, kode, ID, email.{
"mappings": {
"properties": {
"category": {
"type": "text",
"fields": {
"keyword": { "type": "keyword", "ignore_above": 256 }
}
}
}
}
}Dengan pola ini, category dipakai untuk full-text search, dan category.keyword untuk exact match, aggregation, dan sorting. Inilah pola multi-field yang paling sering kalian jumpai.
byte, short, integer, long, float, double — pilih yang paling kecil namun cukup menampung nilai, karena tipe kecil menghemat disk dan mempercepat sort/aggregation. ID numerik yang hanya dibandingkan sebaiknya keyword, bukan long, untuk menghindari kesalahan precision.
Tipe date menyimpan tanggal sebagai timestamp milidetik (epoch_millis). Elasticsearch menerima string ISO 8601 seperti "2026-08-03T10:00:00Z" dan otomatis mengonversinya. date_nanos menambah presisi nanodetik untuk kasus yang membutuhkannya:
{
"mappings": {
"properties": {
"@timestamp": {
"type": "date",
"format": "strict_date_optional_time||epoch_millis"
}
}
}
}boolean — nilai true/false, dipakai untuk flag.binary — data biner ber-encoding base64, tidak bisa dicari.range — integer_range, float_range, date_range untuk menyimpan rentang nilai, lalu query yang menanyakan "apakah nilai X berada dalam rentang ini". Berguna untuk harga diskon, jadwal, atau rentang umur.Field JSON bisa berisi objek — Elasticsearch menyimpannya sebagai object (field name di dalam objek user otomatis menjadi user.name). Masalah muncul dengan array of objects: karena Lucene tidak menyimpan struktur array, relasi antar objek dalam array bisa tercampur. Solusinya nested:
{
"mappings": {
"properties": {
"order_items": {
"type": "nested",
"properties": {
"product": { "type": "keyword" },
"qty": { "type": "integer" }
}
}
}
}
}Dengan nested, tiap objek dalam array diindeks sebagai dokumen tersembunyi terpisah, sehingga query "produk X dengan qty lebih dari Y" menghasilkan jawaban yang benar.
Semua tipe field bisa menampung array — field keyword bisa berisi ["red", "blue"]. Yang perlu diingat: array tidak perlu dideklarasikan di mapping, dan elemen-elemennya harus bertipe sama dengan field.
geo_point menyimpan koordinat (lat, lon) dan memungkinkan query "toko terdekat" dengan geo_distance; geo_shape menyimpan bentuk geometris (polygon, line) untuk query spasial seperti "apakah titik ini di dalam area DKI Jakarta".
Tipe ip menyimpan alamat IPv4/IPv6 dengan validasi otomatis, dan mendukung query range seperti "cari semua log dari subnet 10.0.0.0/24".
join memungkinkan relasi parent-child dalam satu index — misalnya pertanyaan dan jawaban. Berbeda dari nested, relasi ini tidak membebani search seperti nested, tapi menuntut perhatian terhadap routing: dokumen child harus memiliki routing yang sama dengan parent-nya.
Warning
Mapping explosion adalah musuh diam-diam. Jika mapping di-generate dinamis dari data yang tidak terkontrol — misalnya field log dengan nama dinamis seperti user_12345, app_xyz — jumlah field bisa meledak hingga ratusan ribu, membuat cluster kehabisan memori dan crash. Lindungi diri dengan dynamic: strict, ignore_dynamic_beyond_one_hundred (default), atau batas index.mapping.total_fields.limit (default 1000). Episode 25 akan membahas pencegahan ini dalam konteks integrasi aplikasi.
Di episode 5 kalian memahami mapping sebagai cetak biru data: dynamic vs explicit, parameter-parameter penting seperti index, analyzer, doc_values, dan ignore_above; tipe data inti — text vs keyword, numerik, date, boolean, binary, range; serta tipe kompleks — object, nested, array, geo, IP, dan join — dengan kesadaran akan risiko mapping explosion.
Inti yang harus dibawa pulang:
text untuk full-text search, keyword untuk exact match, sort, aggregation.text + .keyword adalah pola paling umum.nested agar query akurat.dynamic dengan bijak untuk mencegah mapping explosion.Sekarang data sudah tersimpan dengan mapping yang benar — saatnya mencari. Di episode 6 kita mulai Search Fundamentals dengan Query DSL: perbedaan URI search vs request body, query context vs filter context, filter _source, pagination dengan from/size dan search_after, serta query-query dasar — match, term, match_phrase, multi_match, query_string, exists, dan range. Sampai jumpa!