โ† Semua pembelajaran / Laravel Nol โ†’ Enterprise
Fase 10 ยท Enterprise & Capstone

Pencarian dengan Scout

Pencarian adalah fitur yang paling sering dibangun dua kali: sekali dengan LIKE, lalu sekali lagi dengan benar setelah datanya bertambah. Scout memberi antarmuka yang sama untuk beberapa mesin di belakangnya.

Sumber asli laravel.com Resmi Rangkuman ~6 menit baca

Intisari

  • LIKE '%kata%' tidak bisa memakai index โ€” ia memindai seluruh tabel.
  • Scout menyediakan satu API untuk beberapa driver: database, Meilisearch, Typesense, Algolia.
  • Indeks diperbarui otomatis lewat event model โ€” dan sebaiknya dijalankan lewat antrean.
  • Query builder mentah tidak memicu pembaruan indeks; itu penyebab indeks jadi basi.
  • Mulai dari driver database; pindah ke mesin sungguhan saat hasilnya sudah terasa kurang.

Kenapa LIKE tidak cukup

Artikel::where('judul', 'like', "%{$kata}%")->get();
MasalahAkibat
Wildcard di awalIndex tidak terpakai; seluruh tabel dipindai
Tanpa peringkat relevansiHasil diurutkan sembarangan, bukan berdasarkan kecocokan
Tanpa stemming"berlari" tidak menemukan "lari"
Tanpa toleransi salah ketik"jakrata" tidak menemukan apa pun
Sulit mencari beberapa kolomOR berlapis yang makin lambat
Membebani database utamaPencarian bersaing dengan lalu lintas biasa

Memakai Scout

composer require laravel/scout
php artisan vendor:publish --provider="Laravel\Scout\ScoutServiceProvider"
class Artikel extends Model
{
    use Searchable;

    // Kolom apa yang masuk indeks โ€” jangan kirim semuanya
    public function toSearchableArray(): array
    {
        return [
            'id'          => (int) $this->id,
            'judul'       => $this->judul,
            'ringkasan'   => $this->ringkasan,
            'isi'         => strip_tags($this->isi),
            'kategori'    => $this->kategori->nama,
            'penulis'     => $this->penulis->nama,
            'terbit_pada' => $this->terbit_pada?->timestamp,
        ];
    }

    // Hanya artikel terbit yang boleh muncul di pencarian
    public function shouldBeSearchable(): bool
    {
        return $this->terbit_pada?->isPast() ?? false;
    }
}
Artikel::search('banjir jakarta')->paginate(20);

Artikel::search('banjir')
    ->where('kategori_id', 3)
    ->orderBy('terbit_pada', 'desc')
    ->take(10)
    ->get();
php artisan scout:import "App\Models\Artikel"      # indeks awal
php artisan scout:flush "App\Models\Artikel"

Memilih driver

DriverKapanCatatan
databaseAwal proyek, data kecilTanpa layanan tambahan; memakai kemampuan pencarian database
collectionTesSemuanya di memori
MeilisearchPilihan mandiri yang baikCepat, toleran salah ketik, mudah dijalankan
TypesenseSerupa MeilisearchKuat untuk pencarian dengan facet
AlgoliaTerkelola penuhSangat cepat; biaya naik seiring jumlah pencarian
OpenSearch (via paket)Sudah di AWSTerkelola AWS; lebih rumit dioperasikan

Mulai dari database, dan pindah ketika ada keluhan nyata. Driver database memakai kemampuan pencarian yang sudah ada di MySQL atau PostgreSQL โ€” cukup untuk puluhan ribu baris, tanpa satu pun layanan tambahan yang harus dioperasikan. Berpindah driver nanti tidak mengubah kode aplikasimu, hanya konfigurasi dan satu perintah scout:import. Itulah nilai utama Scout.

Indeksasi lewat antrean

// config/scout.php
'queue' => true,

Tanpa ini, setiap penyimpanan artikel akan menunggu panggilan jaringan ke mesin pencari sebelum responsnya dikirim. Dengan antrean, penyimpanan tetap cepat dan indeks menyusul beberapa detik kemudian โ€” pertukaran yang hampir selalu tepat.

Query builder mentah tidak memperbarui indeks. Artikel::where(...)->update([...]) dan DB::table('artikel')->delete() melewati event Eloquent, jadi Scout tidak tahu apa-apa. Indeksnya jadi basi tanpa ada yang menyadarinya. Untuk operasi massal, panggil ->searchable() atau ->unsearchable() secara eksplisit setelahnya โ€” atau jadwalkan scout:import berkala sebagai jaring pengaman.

Yang perlu diperhatikan di situs konten

  1. Batasi laju endpoint pencarian. Ia mahal, dan sasaran empuk pengerukan (Fase 4).
  2. Cache hasil untuk kata yang populer โ€” s-maxage pendek sudah sangat menolong.
  3. Jangan kirim seluruh isi artikel ke indeks kalau yang dicari cuma judul dan ringkasan; ukuran indeks memengaruhi biaya dan kecepatan.
  4. Sediakan hasil yang baik untuk kueri kosong โ€” halaman pencarian tanpa hasil adalah jalan buntu.
  5. Catat kueri yang tidak menghasilkan apa pun; itu daftar konten yang dicari pembacamu tapi belum kamu punya.

Alternatif: pencarian vektor

// Laravel 13: kemiripan vektor langsung dari query builder
$dokumen = DB::table('dokumen')
    ->whereVectorSimilarTo('embedding', 'banjir di ibu kota')
    ->limit(10)
    ->get();

Pencarian semantik menemukan dokumen yang bermakna mirip, bukan yang mengandung kata yang sama persis. Ia pelengkap pencarian kata kunci, bukan penggantinya: pembaca yang mengetik nama tokoh tetap mengharapkan kecocokan harfiah. Pola yang lazim adalah menggabungkan keduanya.

Latihan: pasang Scout dengan driver database pada model artikel, batasi indeks ke judul dan ringkasan, lalu bandingkan waktu search() dengan where('judul','like','%โ€ฆ%') pada 100.000 baris. Setelah itu pasang throttle pada rute pencariannya.

Rangkuman ini sengaja dipangkas ke bagian yang dipakai di roadmap. Buka sumber aslinya saat kamu butuh detail lengkap atau referensi parameter.