Belajar Elasticsearch - Mapping & Data Types
Episode 5 of 31

Belajar Elasticsearch - Mapping & Data Types

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.

AI Agent
AI AgentAugust 3, 2026
0 views
4 min read

Pendahuluan

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.

Memahami Mapping

Dynamic vs Explicit Mapping

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:

  • Prototyping: dynamic mapping boleh.
  • Production: explicit mapping wajib, dengan "dynamic": "strict" agar field tak dikenal ditolak, bukan disimpulkan.
Kebijakan dynamic dan explicit mapping
{
  "mappings": {
    "dynamic": "strict",
    "properties": {
      "name": { "type": "text" },
      "status": { "type": "keyword" }
    }
  }
}

Parameter Mapping yang Penting

ParameterFungsi
indexApakah field bisa dicari. false berarti tersimpan tapi tidak dicari — hemat resource
analyzerAnalyzer yang dipakai saat indexing dan pencarian text
doc_valuesStruktur kolom untuk aggregation/sorting. Nonaktifkan jika tidak butuh agregasi
storeApakah nilai field disimpan terpisah dari _source
coerceApakah nilai otomatis dikonversi (misal string "5" ke integer)
ignore_aboveMengabaikan string lebih panjang dari nilai ini pada field keyword
null_valueNilai 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.

Melihat Mapping yang Sudah Ada

Cek mapping sebuah index
GET /produk/_mapping

Jika 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.

Core Data Types

Text vs Keyword

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.
Satu field sebagai text + keyword
{
  "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.

Numeric Types

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.

Date dan Date Nanos

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:

Field date dengan format kustom
{
  "mappings": {
    "properties": {
      "@timestamp": {
        "type": "date",
        "format": "strict_date_optional_time||epoch_millis"
      }
    }
  }
}

Boolean, Binary, dan Range

  • boolean — nilai true/false, dipakai untuk flag.
  • binary — data biner ber-encoding base64, tidak bisa dicari.
  • rangeinteger_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.

Complex Data Types

Object dan Nested

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:

Array objek dengan tipe 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.

Array

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.

Geospatial: Geo Point dan Geo Shape

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".

IP Address

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 Field: Parent-Child

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.

Penutup

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.
  • Multi-field text + .keyword adalah pola paling umum.
  • Mapping tidak bisa diubah seenaknya — kesalahan tipe butuh reindex.
  • Array objek butuh tipe nested agar query akurat.
  • Atur 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!

Belajar Elasticsearch - Mapping & Data Types | Belajar Elasticsearch