Troubleshooting

Mapping Conflict & Tipe Field

Mapping di Elasticsearch mendefinisikan tipe setiap field. Begitu sebuah field punya data, tipenya tidak bisa diubah. Mencoba mengubahnya memunculkan error mapper cannot be changed. Panduan ini menjelaskan kenapa mapping immutable, perbedaan dynamic vs strict, dan solusi resmi: reindex ke index baru dengan mapping yang benar.

Kenapa Mapping Immutable?

Tipe field menentukan bagaimana data ditulis ke struktur indeks Lucene di disk — inverted index untuk text, doc values untuk keyword/numeric, dan seterusnya. Mengubah tipe field yang sudah berisi data akan membuat segmen lama tak kompatibel dengan tulisan baru.

Karena itu Anda boleh menambah field baru atau sub-field, tetapi tidak boleh mengubah tipe field yang sudah ada. Inilah sifat immutable mapping.

Yang masih diizinkan tanpa reindex: menambah field baru, menambah multi-field baru, mengubah beberapa parameter non-struktural seperti ignore_above pada keyword.

Error Tipikal

# mengubah tipe field yang sudah ada
PUT /produk/_mapping
{ "properties": { "harga": { "type": "text" } } }

{
  "error": {
    "type": "illegal_argument_exception",
    "reason": "mapper [harga] cannot be changed from type [long] to [text]"
  },
  "status": 400
}
# konflik lintas-index pada alias / wildcard
{
  "type": "illegal_argument_exception",
  "reason": "Mapper for [harga] conflicts with existing mapper:
    cannot be changed from type [long] to [text]"
}
# strict mapping menolak field tak dikenal
{
  "type": "strict_dynamic_mapping_exception",
  "reason": "mapping set to strict, dynamic introduction of [diskon] within [_doc] is not allowed"
}

Dynamic vs Strict Mapping

Mode dynamicField baru di dokumenCocok untuk
true (default)Otomatis ditambahkan ke mapping.Eksplorasi awal, data tak menentu.
runtimeDitambah sebagai runtime field (tak diindeks).Field jarang dipakai, hemat penyimpanan.
falseDisimpan di _source tapi tidak diindeks/dicari.Menyimpan tanpa membengkakkan mapping.
strictDokumen ditolak (error).Skema matang, cegah ledakan field.
# aktifkan strict mapping
PUT /produk
{
  "mappings": {
    "dynamic": "strict",
    "properties": {
      "nama":  { "type": "text" },
      "harga": { "type": "long" }
    }
  }
}

Solusi: Reindex ke Index Baru

Karena tipe tak bisa diubah di tempat, buat index baru dengan mapping benar lalu salin data.

  1. Periksa mapping lama

    GET /produk/_mapping untuk melihat tipe field saat ini.

  2. Buat index baru dengan mapping benar

    Definisikan tipe yang diinginkan secara eksplisit.

  3. Reindex data

    Salin seluruh dokumen dari index lama ke baru.

  4. Alihkan alias

    Pindahkan alias agar aplikasi langsung memakai index baru tanpa downtime.

# 1) index baru dengan tipe benar + multi-field
PUT /produk-v2
{
  "mappings": {
    "properties": {
      "harga": { "type": "long" },
      "nama":  {
        "type": "text",
        "fields": { "keyword": { "type": "keyword", "ignore_above": 256 } }
      }
    }
  }
}

# 2) reindex
POST /_reindex
{
  "source": { "index": "produk" },
  "dest":   { "index": "produk-v2" }
}

# 3) alihkan alias tanpa downtime
POST /_aliases
{
  "actions": [
    { "remove": { "index": "produk",    "alias": "produk-live" } },
    { "add":    { "index": "produk-v2", "alias": "produk-live" } }
  ]
}
Selalu akses index lewat alias (mis. produk-live) sejak awal. Dengan begitu reindex dan pergantian mapping di masa depan bisa dilakukan tanpa mengubah kode aplikasi. Lihat panduan Reindex Tanpa Downtime untuk detail.

Multi-Fields: Satu Field, Banyak Perilaku

Kebutuhan umum: field teks yang bisa dicari full-text dan diagregasi/diurutkan. Multi-fields menyelesaikannya.

"nama": {
  "type": "text",                 # untuk pencarian full-text
  "fields": {
    "keyword": { "type": "keyword" }  # untuk agregasi & sort
  }
}
# cari full-text
GET /produk/_search
{ "query": { "match": { "nama": "kopi arabika" } } }

# agregasi pakai sub-field keyword
GET /produk/_search
{ "aggs": { "per_nama": { "terms": { "field": "nama.keyword" } } } }

Tips Merancang Mapping

  • Definisikan mapping eksplisit untuk index produksi; jangan andalkan tebakan dynamic mapping.
  • Pakai keyword untuk ID, status, dan field yang difilter/diagregasi; text hanya untuk pencarian full-text.
  • Aktifkan dynamic: strict begitu skema matang untuk mencegah field tak terduga.
  • Gunakan index template agar mapping konsisten di seluruh index berpola sama.
  • Selalu sediakan alias sejak awal agar reindex di masa depan bebas downtime.

FAQ Mapping Conflict

Kenapa saya tidak bisa mengubah tipe field yang sudah ada?

Mapping di Elasticsearch bersifat immutable untuk field yang sudah punya data. Tipe field menentukan struktur indeks Lucene di disk; mengubahnya akan membuat data lama tidak konsisten dengan struktur baru. Karena itu Elasticsearch menolak dengan error seperti "mapper [x] cannot be changed". Solusinya adalah membuat index baru dengan mapping yang benar lalu reindex.

Apa itu mapping conflict pada wildcard/alias?

Konflik terjadi ketika dua index yang dicakup pola/alias yang sama mendefinisikan field bernama sama dengan tipe berbeda (misal field price sebagai long di satu index dan text di index lain). Query lintas-index pada field itu akan gagal. Selesaikan dengan menyeragamkan mapping melalui reindex.

Apa beda dynamic mapping dan strict mapping?

Dynamic mapping (default) membuat Elasticsearch menebak dan menambah field baru otomatis saat dokumen masuk. Strict mapping (dynamic: strict) menolak dokumen yang memuat field tak dikenal. Strict mencegah ledakan field dan kesalahan tipe, cocok untuk skema yang sudah matang.

Bisakah satu field punya beberapa tipe sekaligus?

Bisa, lewat multi-fields. Misalnya field name bertipe text untuk pencarian full-text, dengan sub-field name.keyword bertipe keyword untuk agregasi dan sorting. Ini cara standar mendapat dua perilaku tanpa menyimpan data dua kali secara eksplisit.

Reindex tanpa mengganggu layanan

Pelajari pola reindex memakai alias agar perubahan mapping berjalan mulus tanpa downtime.

Panduan Reindex Tanpa Downtime