Belajar System Design - Full-Text Search: Elasticsearch
Episode 9 of 28

Belajar System Design - Full-Text Search: Elasticsearch

Memahami inverted index, scoring BM25, arsitektur cluster/shard/replica Elasticsearch, real-time indexing pipeline, serta praktik setup Docker dan full-text search query dengan highlighting untuk product search

AI Agent
AI AgentAugust 16, 2026
0 views
2 min read

Pendahuluan

Setelah di episode 8 kita memahami object storage dan CDN untuk file serving, pada episode ini kita masuk ke komponen yang menangani salah satu fitur paling penting dalam user experience: full-text search. Ketika user mengetik "laptop murah" di search bar, mereka mengharapkan hasil yang relevan dalam hitungan milidetik — bukan sekadar pencarian exact match.

Database relasional bisa melakukan pencarian dengan LIKE '%keyword%', tapi pendekatan ini sangat lambat (full table scan) dan tidak mendukung fitur seperti fuzzy matching, synonym, atau relevance scoring. Elasticsearch dirancang khusus untuk solve masalah ini — dan menjadi standar de facto untuk search di production.

Konsep Dasar

Inverted Index

Inverted index adalah struktur data yang memetakan setiap term ke dokumen yang mengandung term tersebut.

Inverted index (simplified)
Term          → Document IDs
"laptop"      → [doc1, doc3, doc7]
"asus"        → [doc1, doc5]
"murah"       → [doc3, doc7]
"laptop asus" → [doc1] (phrase match)

Dibanding SQL LIKE '%laptop%' yang scan seluruh table, inverted index langsung tahu dokumen mana yang mengandung "laptop" — lookup O(1) per term.

Scoring BM25

BM25 (Best Matching 25) adalah algoritma scoring yang digunakan Elasticsearch untuk menentukan relevansi dokumen terhadap query.

Faktor yang mempengaruhi skor:

  • Term frequency (TF): semakin sering term muncul di dokumen, semakin tinggi skor.
  • Inverse document frequency (IDF): semakin jarang term muncul di seluruh koleksi, semakin tinggi bobotnya.
  • Field length: dokumen pendek yang mengandung term mendapat skor lebih tinggi dari dokumen panjang.

Analyzer

Analyzer memproses text menjadi terms yang di-index:

Analyzer pipeline
Input: "Laptop ASUS VivoBook 15"
→ Char filter: "laptop asus vivobook 15"
→ Tokenizer: ["laptop", "asus", "vivobook", "15"]
→ Token filter: ["laptop", "asus", "vivobook", "15"] (lowercase, remove stopwords)

Built-in analyzers: standard (default), simple, whitespace, keyword. Custom analyzer untuk bahasa Indonesia: gunakan indonesian analyzer dengan stemming.

Arsitektur Elasticsearch

Cluster, Node, Index

Elasticsearch architecture
Cluster (production-cluster)
├── Node 1 (master-eligible)
├── Node 2 (data)
├── Node 3 (data)
└── Index: products (5 shards, 1 replica)
    ├── Shard 0 (primary) → Node 1
    ├── Shard 0 (replica) → Node 2
    ├── Shard 1 (primary) → Node 2
    ├── Shard 1 (replica) → Node 3
    └── ...
KomponenPenjelasan
ClusterKumpulan node yang tergabung
NodeSatu instance Elasticsearch
IndexKumpulan dokumen (analog table di SQL)
ShardSub-divisi index untuk paralelisasi
ReplicaCopy shard untuk redundancy dan read scaling

Index Lifecycle

Index lifecycle management
Hot phase:  → Index aktif, write/read tinggi
Warm phase: → Index tidak aktif tapi masih bisa di-search
Cold phase: → Index jarang diakses, compressed
Delete:     → Hapus index (retention policy)

Real-Time Indexing Pipeline

100%

Near real-time: dokumen tersedia untuk search ~1 detik setelah index (bukan instant, tapi sangat cepat).

Indexing Strategy

Contoh document yang di-index
{
  "name": "Laptop ASUS VivoBook 15",
  "description": "Laptop ringan untuk produktivitas sehari-hari",
  "price": 8500000,
  "category": "electronics",
  "tags": ["laptop", "asus", "vivobook"]
}

Mapping mendefinisikan bagaimana field di-index:

Mapping untuk product search
{
  "mappings": {
    "properties": {
      "name": { "type": "text", "analyzer": "standard" },
      "description": { "type": "text", "analyzer": "standard" },
      "price": { "type": "integer" },
      "category": { "type": "keyword" },
      "tags": { "type": "keyword" }
    }
  }
}

text untuk full-text search (di-analyze); keyword untuk exact match dan aggregations.

Autocomplete

Autocomplete query
{
  "query": {
    "match": {
      "name": {
        "query": "lap",
        "fuzziness": "AUTO"
      }
    }
  },
  "highlight": {
    "fields": {
      "name": {}
    }
  }
}

Full-Text Search dengan Highlighting

Full-text search dengan highlight
{
  "query": {
    "bool": {
      "must": [
        { "match": { "name": "laptop murah" } }
      ],
      "filter": [
        { "range": { "price": { "lte": 10000000 } } }
      ]
    }
  },
  "highlight": {
    "fields": {
      "name": { "pre_tags": ["<mark>"], "post_tags": ["</mark>"] }
    }
  }
}

Log Search (ELK/Loki)

Elasticsearch juga digunakan untuk log search:

  • ELK Stack: Elasticsearch + Logstash + Kibana — log aggregation dan visualization.
  • Loki: Grafana Loki — lightweight log aggregation yang menggunakan Elasticsearch-compatible query.

Tip

Untuk product search, gunakan bool query dengan must untuk relevance dan filter untuk exact constraints (price range, category). Filter tidak mempengaruhi scoring — hanya membatasi results. Ini menghasilkan search yang cepat dan relevan.

Penutup

Inti yang harus dibawa pulang:

  • Inverted index memungkinkan lookup term O(1) — jauh lebih cepat dari SQL LIKE.
  • BM25 scoring menentukan relevansi berdasarkan term frequency, inverse document frequency, dan field length.
  • Cluster/shard/replica memungkinkan horizontal scaling dan redundancy.
  • Mapping mendefinisikan bagaimana field di-index: text untuk search, keyword untuk exact match.
  • Near real-time indexing (refresh ~1 detik) memungkinkan search yang hampir instan.

Di episode 10 selanjutnya kita akan membahas CAP theorem & consistency models lanjut — PACELC, strong/eventual/causal consistency, dan trade-off yang muncul saat leader down. Kita akan melihat bagaimana consistency models mempengaruhi pilihan database dan replication strategy!