---
title: 'Table & Lookup'
description: "Operasi tabel tingkat lanjut untuk pencarian data, pengindeksan, dan kueri."
navigation:
  icon: 'i-ph-code-block'
seo:
  title: 'Table & Lookup'
  description: "Operasi tabel tingkat lanjut untuk pencarian data, pengindeksan, dan kueri."
---

## Gambaran Umum

Operator tabel bekerja dengan **array berisi objek** (disebut sebagai "tabel") untuk melakukan pencarian, penggeledahan, dan kueri. Operator ini sangat penting untuk bekerja dengan data terstruktur seperti tabel tarif, peta konfigurasi, dan data bergaya relasional di dalam evaluasi JSON.

### Apa itu Tabel?

Dalam JSON-Eval-RS, sebuah "tabel" adalah array objek di mana setiap objek merepresentasikan satu baris data:

```json
[
  {"id": 1, "name": "Alice", "age": 30},
  {"id": 2, "name": "Bob", "age": 25},
  {"id": 3, "name": "Charlie", "age": 35}
]
```

Setiap objek memiliki struktur (kolom/field) yang sama, mirip dengan tabel database atau spreadsheet.

### Kasus Penggunaan Umum

- **Tabel Tarif**: Mencari tarif asuransi, braket pajak, atau tingkatan harga berdasarkan rentang.
- **Peta Konfigurasi**: Menemukan pengaturan atau parameter berdasarkan kunci (key).
- **Penggabungan Data (Data Joins)**: Mengambil data terkait dari berbagai tabel.
- **Penyaringan & Pencarian**: Menemukan baris yang cocok dengan kriteria tertentu.
- **Pencarian Berbasis Rentang**: Menemukan nilai yang berada di dalam batas minimum/maksimum.

### Kategori Operator

1. **Akses Langsung**: `VALUEAT`, `MAXAT` - Mengambil nilai berdasarkan posisi.
2. **Cari/Temukan**: `INDEXAT`, `MATCH`, `MATCHRANGE`, `CHOOSE` - Menemukan indeks baris.
3. **Kueri Kompleks**: `FINDINDEX` - Pencarian kondisional tingkat lanjut.

Kebanyakan alur kerja menggabungkan ini: gunakan operator pencarian untuk menemukan indeks baris, lalu gunakan `VALUEAT` untuk mengambil nilai yang diinginkan.

## `VALUEAT` - Mengambil Nilai dari Tabel

Mengambil nilai dari tabel (array berisi objek) berdasarkan indeks baris dan nama kolom (opsional).

### Sintaksis
```json
{"VALUEAT": [table, row_index]}
{"VALUEAT": [table, row_index, column_name]}
```

### Parameter
- **table** (array): Array berisi objek.
- **row_index** (number): Indeks baris (berbasis 0).
- **column_name** (string, opsional): Nama kolom/field.

### Tipe Kembalian
Any - Seluruh objek baris atau nilai kolom tertentu, `null` jika tidak ditemukan.

### Contoh

**Mengambil seluruh baris:**
```json
// Data: {"table": [
//   {"name": "Alice", "age": 30},
//   {"name": "Bob", "age": 25},
//   {"name": "Charlie", "age": 35}
// ]}
{"VALUEAT": [{"var": "table"}, 1]}
// → {"name": "Bob", "age": 25}
```

**Mengambil kolom spesifik:**
```json
{"VALUEAT": [{"var": "table"}, 1, "name"]}  // → "Bob"
{"VALUEAT": [{"var": "table"}, 2, "age"]}   // → 35
```

**Di luar batas (Out of bounds):**
```json
{"VALUEAT": [{"var": "table"}, -1]}   // → null
{"VALUEAT": [{"var": "table"}, 999]}  // → null
```

**Indeks dinamis:**
```json
{"VALUEAT": [
  {"var": "rates"},
  {"INDEXAT": [{"var": "age"}, {"var": "rates"}, "minAge"]},
  "rate"
]}
```

**Dengan perulangan FOR:**
```json
{"FOR": [
  0,
  {"-": [{"length": {"var": "table"}}, 1]},
  {"VALUEAT": [{"var": "table"}, {"var": "$iteration"}, "value"]}
]}
```

---

## `MAXAT` - Mengambil Nilai Baris Terakhir

Mengembalikan nilai kolom dari baris terakhir dalam sebuah tabel.

### Sintaksis
```json
{"MAXAT": [table, column_name]}
```

### Parameter
- **table** (array): Array berisi objek.
- **column_name** (string): Nama field yang akan diambil nilainya.

### Tipe Kembalian
Any - Nilai dari kolom baris terakhir, `null` jika tabel kosong.

### Contoh

**Mengambil nilai terakhir:**
```json
// Data: {"table": [
//   {"name": "Alice", "score": 85},
//   {"name": "Bob", "score": 92},
//   {"name": "Charlie", "score": 78}
// ]}
{"MAXAT": [{"var": "table"}, "score"]}  // → 78 (Skor Charlie)
```

**Asumsi data terurut:**
```json
// Jika tabel terurut berdasarkan umur secara menaik, ambil umur maksimum
{"MAXAT": [{"var": "sortedByAge"}, "age"]}
```

**Mengambil entri terbaru:**
```json
{"MAXAT": [{"var": "history"}, "timestamp"]}
```

---

## `INDEXAT` - Mencari Indeks

Mencari indeks elemen di dalam tabel dengan mencocokkan nilai field.

### Sintaksis
```json
{"INDEXAT": [lookup_value, table, field]}
{"INDEXAT": [lookup_value, table, field, range]}
```

### Parameter
- **lookup_value** (any): Nilai yang dicari.
- **table** (array): Array berisi objek untuk dicari.
- **field** (string): Nama field yang dibandingkan.
- **range** (boolean, opsional): 
  - `false` atau tidak disertakan: **Pencarian Persis (Exact match)** - mencari baris di mana `field == lookup_value`.
  - `true`: **Pencarian Rentang (Range search)** - mencari baris **pertama** di mana `field <= lookup_value` (asumsi tabel sudah terurut berdasarkan field tersebut secara menaik/ascending).

### Tipe Kembalian
Number - Indeks baris yang cocok (berbasis 0), atau `-1` jika tidak ditemukan.

### Contoh

**Pencarian Persis:**
```json
// Data: {"table": [
//   {"id": 100, "name": "Alice"},
//   {"id": 200, "name": "Bob"},
//   {"id": 300, "name": "Charlie"}
// ]}
{"INDEXAT": [200, {"var": "table"}, "id"]}  // → 1
```

**Tidak ditemukan:**
```json
{"INDEXAT": [999, {"var": "table"}, "id"]}  // → -1
```

**Pencarian Rentang (Asumsi terurut):**
```json
// Data: {"brackets": [
//   {"threshold": 0, "rate": 0.1},
//   {"threshold": 10000, "rate": 0.15},
//   {"threshold": 50000, "rate": 0.25}
// ]}

// Cari baris pertama di mana threshold <= 25000
{"INDEXAT": [25000, {"var": "brackets"}, "threshold", true]}
// → 1 (threshold 10000 <= 25000)

// Cari baris pertama di mana threshold <= 75000
{"INDEXAT": [75000, {"var": "brackets"}, "threshold", true]}
// → 2 (threshold 50000 <= 75000)
```

**Penting**: Mode rentang (range) mengharapkan tabel sudah **terurut** berdasarkan field secara menaik. Ini mengembalikan baris **pertama** (paling kiri) di mana nilai field kurang dari atau sama dengan nilai yang dicari.

**Cari indeks dan ambil nilai:**
```json
{"VALUEAT": [
  {"var": "table"},
  {"INDEXAT": [{"var": "searchId"}, {"var": "table"}, "id"]},
  "name"
]}
```

---

## `MATCH` - Mencocokkan Baris dengan Kondisi

Mencari indeks baris pertama yang cocok dengan semua pasangan field-nilai yang ditentukan.

### Sintaksis
```json
{"MATCH": [table, value1, field1, value2, field2, ...]}
```

### Parameter
- **table** (array): Array berisi objek.
- **value, field** (pasangan): Pasangan nilai-field yang harus dicocokkan (semua harus cocok - logika AND).

### Tipe Kembalian
Number - Indeks baris pertama yang cocok, atau `-1` jika tidak ditemukan.

### Contoh

**Kondisi tunggal:**
```json
// Data: {"table": [
//   {"name": "Alice", "age": 30, "city": "Jakarta"},
//   {"name": "Bob", "age": 25, "city": "Surabaya"},
//   {"name": "Charlie", "age": 35, "city": "Jakarta"}
// ]}
{"MATCH": [{"var": "table"}, "Alice", "name"]}  // → 0
```

**Beberapa kondisi (AND):**
```json
{"MATCH": [{"var": "table"}, "Alice", "name", "Jakarta", "city"]}
// → 0 (Alice di Jakarta)

{"MATCH": [{"var": "table"}, "Bob", "name", "Jakarta", "city"]}
// → -1 (Bob tidak di Jakarta)
```

**Tidak ditemukan:**
```json
{"MATCH": [{"var": "table"}, "Siti", "name"]}  // → -1
```

**Mengambil baris yang cocok:**
```json
{"VALUEAT": [
  {"var": "table"},
  {"MATCH": [{"var": "table"}, "Alice", "name"]}
]}
```

---

## `MATCHRANGE` - Mencocokkan Nilai dalam Rentang

Menemukan indeks baris pertama di mana suatu nilai berada di antara field minimum dan maksimum.

### Sintaksis
```json
{"MATCHRANGE": [table, min_field, max_field, value]}
```

### Parameter
- **table** (array): Array berisi objek dengan field rentang.
- **min_field** (string): Nama field untuk nilai minimum.
- **max_field** (string): Nama field untuk nilai maksimum.
- **value** (number): Nilai yang akan diperiksa.

### Tipe Kembalian
Number - Indeks baris pertama di mana min <= value <= max, atau `-1` jika tidak ditemukan.

### Contoh

**Pencarian tabel tarif:**
```json
// Data: {"rates": [
//   {"min_age": 0, "max_age": 25, "rate": 0.05},
//   {"min_age": 26, "max_age": 40, "rate": 0.07},
//   {"min_age": 41, "max_age": 60, "rate": 0.09}
// ]}

{"MATCHRANGE": [{"var": "rates"}, "min_age", "max_age", 30]}
// → 1 (30 berada di rentang 26-40)

{"MATCHRANGE": [{"var": "rates"}, "min_age", "max_age", 50]}
// → 2 (50 berada di rentang 41-60)
```

**Mengambil tarif berdasarkan umur:**
```json
{"VALUEAT": [
  {"var": "rates"},
  {"MATCHRANGE": [{"var": "rates"}, "min_age", "max_age", {"var": "age"}]},
  "rate"
]}
```

**Braket Pajak:**
```json
{"MATCHRANGE": [
  {"var": "taxBrackets"},
  "min_income",
  "max_income",
  {"var": "income"}
]}
```


## `CHOOSE` - Memilih Kecocokan Acak/Pertama

Menemukan indeks dari baris mana pun (biasanya yang pertama) yang cocok dengan kondisi. Mirip dengan `MATCH` tetapi dengan keterurutan yang kurang dapat diprediksi.

### Sintaksis
```json
{"CHOOSE": [table, value, field, ...]}
```

### Parameter
- **table** (array): Array berisi objek.
- **value, field** (pasangan): Satu atau lebih pasangan nilai-field untuk dicocokkan (semua harus cocok).

### Tipe Kembalian
Number - Indeks baris yang cocok, atau `-1` jika tidak ditemukan.

### Kapan Menggunakan CHOOSE vs MATCH

- **MATCH**: Menjamin pengembalian baris pertama yang cocok. Gunakan untuk hasil yang dapat diprediksi.
- **CHOOSE**: Mengembalikan baris mana pun yang cocok (tergantung implementasi). Gunakan ketika urutan tidak penting atau untuk optimasi performa dalam skenario tertentu.

⚠️ **Catatan**: Dalam kebanyakan kasus, lebih disarankan menggunakan `MATCH` untuk perilaku yang dapat diprediksi. `CHOOSE` ada untuk kompatibilitas dan skenario performa spesifik di mana kecocokan pertama tidak menjadi masalah.

### Contoh

**Menemukan kecocokan mana pun:**
```json
// Data: {"products": [
//   {"name": "Widget", "category": "A", "price": 10},
//   {"name": "Gadget", "category": "B", "price": 20},
//   {"name": "Tool", "category": "A", "price": 15}
// ]}

{"CHOOSE": [{"var": "products"}, "A", "category"]}
// → Bisa mengembalikan 0 atau 2 (item apa pun di kategori A)
// Hasil sebenarnya tergantung pada implementasi
```

**Mengambil produk yang cocok:**
```json
{"VALUEAT": [
  {"var": "products"},
  {"CHOOSE": [{"var": "products"}, "A", "category"]},
  "name"
]}
// → "Widget" atau "Tool" (mana pun kecocokan yang dikembalikan)
```

**Beberapa kondisi:**
```json
// Temukan produk apa pun di mana category="A" DAN price=15
{"CHOOSE": [{"var": "products"}, "A", "category", 15, "price"]}
// → 2 (hanya satu kecocokan, jadi deterministik dalam kasus ini)
```

**Skenario praktis - sumber daya apa pun yang tersedia:**
```json
// Ambil server apa pun yang tersedia (urutan tidak penting)
{"VALUEAT": [
  {"var": "servers"},
  {"CHOOSE": [{"var": "servers"}, true, "available"]},
  "hostname"
]}
```

---

## `FINDINDEX` - Pencarian dengan Kondisi Kompleks

Menemukan indeks baris pertama yang cocok dengan kondisi kompleks dengan sintaksis yang ergonomis. Ini adalah operator pencarian yang paling fleksibel, mendukung berbagai format kondisi.

### Sintaksis
```json
{"FINDINDEX": [table, condition1, condition2, ...]}
```

### Format Kondisi

`FINDINDEX` mendukung **tiga format** kondisi, yang dapat dicampur dan dicocokkan:

#### 1. String Literal - Pemeriksaan Kebenaran Field (Truthiness)
Format paling sederhana: memeriksa apakah suatu field ada dan bernilai benar (truthy).

```json
"fieldName"  // Memeriksa apakah row.fieldName bernilai truthy (bukan null, false, 0, atau string kosong)
```

**Contoh:**
```json
// Temukan baris pertama di mana field "active" bernilai truthy
{"FINDINDEX": [{"var": "users"}, "active"]}
```

#### 2. Array Triplet - Operasi Perbandingan
Format: `[operator, value, field]` - Membandingkan field baris terhadap suatu nilai.

```json
[">", 18, "age"]          // row.age > 18
["==", "active", "status"] // row.status == "active"
["<=", 100, "price"]       // row.price <= 100
["!=", null, "email"]      // row.email != null
```

**Operator yang didukung:** `==`, `!=`, `>`, `>=`, `<`, `<=`

**Contoh:**
```json
// Temukan user pertama di mana age > 18
{"FINDINDEX": [{"var": "users"}, [">", 18, "age"]]}
```

#### 3. Ekspresi Objek - Kekuatan Logika Penuh
Gunakan ekspresi JSON-Eval-RS apa pun untuk fleksibilitas maksimum.

```json
{">": [{"var": "score"}, 70]}
{"and": [
  {">": [{"var": "age"}, 18]},
  {"==": [{"var": "status"}, "active"]}
]}
```

**Contoh:**
```json
// Temukan user pertama di mana score > 70
{"FINDINDEX": [
  {"var": "users"},
  {">": [{"var": "score"}, 70]}
]}
```

### Menggabungkan Kondisi (Logika AND)

Semua kondisi yang diberikan harus bernilai benar (logika AND). Anda dapat mencampur berbagai format:

```json
{"FINDINDEX": [
  {"var": "users"},
  "verified",                          // String: verified bernilai truthy
  [">", 18, "age"],                    // Array: age > 18
  {"!=": [{"var": "email"}, null]}     // Objek: email tidak null
]}
// Menemukan user pertama di mana: verified DAN age > 18 DAN email tidak null
```

### Tipe Kembalian
Number - Indeks baris pertama yang cocok, atau `-1` jika tidak ditemukan.

### Contoh

**Pemeriksaan field sederhana:**
```json
// Data: {"items": [
//   {"value": 10, "active": false},
//   {"value": 20, "active": true},
//   {"value": 30, "active": true}
// ]}

{"FINDINDEX": [{"var": "items"}, "active"]}
// → 1 (baris pertama di mana active bernilai truthy)
```

**Dengan perbandingan:**
```json
{"FINDINDEX": [
  {"var": "items"},
  [">", 15, "value"]
]}
// → 1 (baris pertama di mana value > 15, yaitu 20)
```

**Beberapa kondisi (AND):**
```json
{"FINDINDEX": [
  {"var": "items"},
  "active",
  [">", 15, "value"]
]}
// → 2 (baris pertama di mana active=true DAN value > 15)
// Baris pada indeks 1 memiliki value=20 tetapi kita butuh kedua kondisi
```

**Logika kompleks dengan ekspresi objek:**
```json
{"FINDINDEX": [
  {"var": "users"},
  {">": [{"var": "score"}, 70]},
  {"==": [{"var": "status"}, "verified"]}
]}
// Temukan user terverifikasi pertama dengan skor > 70
```

**Pencocokan string:**
```json
{"FINDINDEX": [
  {"var": "products"},
  ["==", "electronics", "category"],
  [">", 50, "price"]
]}
// Temukan produk elektronik pertama di atas $50
```

**Memeriksa null/undefined:**
```json
{"FINDINDEX": [
  {"var": "records"},
  ["!=", null, "email"]  // Memiliki email
]}
// Temukan record pertama dengan email yang tidak null
```

### Format Mana yang Harus Digunakan?

- **String literal** (`"field"`) - Ketika Anda hanya perlu memeriksa apakah suatu field ada/bernilai truthy.
- **Array triplet** (`["op", value, "field"]`) - Untuk perbandingan sederhana. Bersih dan mudah dibaca.
- **Ekspresi objek** (`{">": [...]}`) - Untuk logika kompleks, operasi bertingkat, atau ketika Anda membutuhkan kondisi OR.

**Saran Ahli**: Gunakan array triplet untuk keterbacaan yang lebih baik jika memungkinkan. Mereka lebih ringkas daripada ekspresi objek untuk perbandingan sederhana.

---

## Contoh Kompleks

Contoh-contoh ini mendemonstrasikan pola dunia nyata yang menggabungkan beberapa operator tabel.

### Pencarian dengan Fallback (Pilihan Cadangan)

**Kasus penggunaan:** Mengambil nilai dari tabel, tetapi memberikan nilai default jika tidak ditemukan.

```json
{"ifnull": [
  {"VALUEAT": [
    {"var": "table"},
    {"INDEXAT": [{"var": "key"}, {"var": "table"}, "id"]},
    "value"
  ]},
  "default"
]}
```

**Cara kerja:**
1. `INDEXAT` mencari baris di mana `id` cocok dengan `key`.
2. `VALUEAT` mengambil field `value` dari baris tersebut.
3. `ifnull` mengembalikan "default" jika langkah 2 mengembalikan `null` (ketika indeks adalah `-1`).

### Pencarian Multi-Tabel

**Kasus penggunaan:** Menemukan baris yang cocok dengan kriteria pada beberapa field yang berbeda.

```json
{"VALUEAT": [
  {"var": "rates"},
  {"MATCH": [
    {"var": "rates"},
    {"var": "category"},
    "category",
    {"var": "type"},
    "type"
  ]},
  "multiplier"
]}
```

**Cara kerja:**
1. `MATCH` menemukan baris pertama di mana kedua kondisi ini terpenuhi:
   - field `category` sama dengan nilai di `{"var": "category"}`
   - field `type` sama dengan nilai di `{"var": "type"}`
2. `VALUEAT` mengekstrak `multiplier` dari baris yang cocok tersebut.

### Kalkulasi Berbasis Rentang

**Kasus penggunaan:** Menerapkan tarif yang berbeda berdasarkan braket pendapatan (seperti perhitungan pajak).

```json
{"*": [
  {"var": "amount"},
  {"VALUEAT": [
    {"var": "brackets"},
    {"MATCHRANGE": [
      {"var": "brackets"},
      "min",
      "max",
      {"var": "income"}
    ]},
    "rate"
  ]}
]}
```

**Cara kerja:**
1. `MATCHRANGE` menemukan braket di mana `min <= income <= max`.
2. `VALUEAT` mengambil `rate` dari braket tersebut.
3. Kalikan `amount` dengan `rate` yang ditemukan.

**Contoh data:**
```json
{
  "income": 35000,
  "amount": 1000,
  "brackets": [
    {"min": 0, "max": 25000, "rate": 0.10},
    {"min": 25001, "max": 50000, "rate": 0.15},
    {"min": 50001, "max": 999999, "rate": 0.25}
  ]
}
// Hasil: 1000 * 0.15 = 150
```

### Pola Temukan dan Ambil (Find and Update Pattern)

**Kasus penggunaan:** Mengambil item dengan aman jika ada, atau mengembalikan null jika tidak.

```json
{
  "let": {
    "index": {"FINDINDEX": [{"var": "items"}, "selected"]},
    "found": {">": [{"var": "index"}, -1]}
  },
  "in": {
    "if": [
      {"var": "found"},
      {"VALUEAT": [{"var": "items"}, {"var": "index"}]},
      null
    ]
  }
}
```

**Cara kerja:**
1. Temukan indeks dari item pertama yang dipilih (`selected`).
2. Simpan apakah item ditemukan (`found` = index > -1).
3. Jika ditemukan, kembalikan objek item lengkap; jika tidak, kembalikan `null`.

**Mengapa menggunakan pola ini:** Memisahkan pencarian dari pengambilan nilai, membuat logika lebih jelas dan memungkinkan penggunaan ulang indeks.

### Pencarian Tabel Bersarang (Nested Table Lookup)

**Kasus penggunaan:** Pencarian gaya relasional pada tabel master-detail.

```json
{"VALUEAT": [
  {"VALUEAT": [
    {"var": "masterTable"},
    {"INDEXAT": [{"var": "masterId"}, {"var": "masterTable"}, "id"]},
    "detailTable"
  ]},
  {"INDEXAT": [{"var": "detailId"}, {"var": "detailTable"}, "id"]},
  "value"
]}
```

**Cara kerja:**
1. Temukan record master berdasarkan `masterId`.
2. Ekstrak array `detailTable` dari record master tersebut.
3. Di dalam tabel detail tersebut, temukan record yang cocok dengan `detailId`.
4. Ekstrak `value` dari record detail tersebut.

**Contoh struktur data:**
```json
{
  "masterId": 1,
  "detailId": 101,
  "masterTable": [
    {
      "id": 1,
      "name": "Master A",
      "detailTable": [
        {"id": 101, "value": "Detail Value A"},
        {"id": 102, "value": "Detail Value B"}
      ]
    }
  ]
}
// Hasil: "Detail Value A"
```

### Tarif Berbasis Umur dengan Rentang

**Kasus penggunaan:** Kalkulasi asuransi/akturia menggunakan tabel mortalitas.

```json
{"VALUEAT": [
  {"$ref": "$params.mortality_table"},
  {"MATCHRANGE": [
    {"$ref": "$params.mortality_table"},
    "min_age",
    "max_age",
    {"var": "current_age"}
  ]},
  "rate"
]}
```

**Cara kerja:**
1. Mereferensikan tabel mortalitas dari parameter.
2. Menemukan braket umur yang berisi `current_age`.
3. Mengembalikan tarif mortalitas untuk braket tersebut.

**Penting:** Ini menggunakan `$ref` untuk mereferensikan parameter eksternal, sangat berguna ketika data tabel besar atau dibagikan di berbagai kalkulasi.

### Pencarian Kondisional Berdasarkan Berbagai Tabel

**Kasus penggunaan:** Memilih di antara tabel tarif yang berbeda berdasarkan kondisi, lalu melakukan pencarian.

```json
{
  "let": {
    "selectedTable": {
      "if": [
        {"var": "isPremium"},
        {"var": "premiumRates"},
        {"var": "standardRates"}
      ]
    },
    "rateIndex": {"INDEXAT": [
      {"var": "age"},
      {"var": "selectedTable"},
      "minAge"
    ]}
  },
  "in": {
    "VALUEAT": [
      {"var": "selectedTable"},
      {"var": "rateIndex"},
      "rate"
    ]
  }
}
```

**Cara kerja:**
1. Memilih tabel mana yang akan digunakan berdasarkan flag `isPremium`.
2. Menemukan baris tarif yang sesuai di tabel yang dipilih.
3. Mengekstrak nilai tarif.
4. Dengan menggunakan `let`, kita menghindari pengulangan logika pemilihan tabel.

---

## Tabel Perbandingan

| Operator | Kasus Penggunaan | Tipe Kecocokan | Terpilih |
|----------|------------------|----------------|----------|
| **VALUEAT** | Akses langsung berdasarkan indeks | Berbasis indeks | Nilai atau baris |
| **MAXAT** | Mengambil nilai baris terakhir | Elemen terakhir | Nilai kolom |
| **INDEXAT** | Mencari berdasarkan kecocokan persis | Persis atau rentang | Indeks |
| **MATCH** | Mencari berdasarkan beberapa field | Persis (AND) | Indeks |
| **MATCHRANGE** | Mencari berdasarkan nilai dalam rentang | Rentang | Indeks |
| **CHOOSE** | Mencari kecocokan mana pun | Persis | Indeks |
| **FINDINDEX** | Kondisi kompleks | Logika kustom | Indeks |

---

## Praktik Terbaik

### 1. Gabungkan Operator untuk Pencarian

Operator tabel dirancang untuk bekerja bersama. Kebanyakan pola menggunakan operator pencarian untuk menemukan indeks, lalu `VALUEAT` untuk mengambil data.

```json
// ✅ Pola standar
{"VALUEAT": [table, {"INDEXAT": [value, table, field]}, column]}
```

**Mengapa:** Pemisahan kekhawatiran ini membuat logika lebih jelas dan memungkinkan pemeriksaan null pada indeks.

### 2. Selalu Periksa Jika Tidak Ditemukan (-1)

Operator pencarian mengembalikan `-1` ketika tidak ada kecocokan yang ditemukan. Selalu tangani kasus ini.

```json
// ✅ Pendekatan aman
{
  "let": {
    "idx": {"INDEXAT": [value, table, field]}
  },
  "in": {
    "if": [
      {">": [{"var": "idx"}, -1]},
      {"VALUEAT": [{"var": "table"}, {"var": "idx"}, "column"]},
      "defaultValue"
    ]
  }
}
```

### 3. Pastikan Tabel Terurut untuk Pencarian Rentang

Fungsi seperti `INDEXAT` dengan mode `range: true` mengharapkan tabel sudah terurut secara menaik (ascending). Jika tidak terurut, hasilnya mungkin tidak terduga atau salah.

### 4. Gunakan Triplet pada `FINDINDEX` untuk Keterbacaan

Gunakan format array triplet `["op", value, "field"]` untuk perbandingan sederhana. Format ini jauh lebih ringkas dan mudah dibaca daripada ekspresi objek penuh untuk tugas-tugas sederhana.
