Lewati ke konten

Pencarian Teks Terindeks

Pencarian teks terindeks adalah versi pencarian teks dengan cache hangat. Pemanggilan pertama membuat penyimpanan di disk untuk trigram dan posting pengenal; pemanggilan berikutnya menggunakan penyimpanan tersebut untuk melewati file yang jelas tidak mungkin memuat pola. Hasilnya, latensi jauh lebih rendah untuk kueri berulang pada repositori besar tanpa menambahkan proses daemon atau watcher.

Permukaan teks hangat kini mencakup:

  • pencarian indeks tunggal
  • --index-dir pencarian multiindeks berulang
  • pencarian set berbasis manifes
  • penanganan data usang yang memperhatikan siklus hidup
  • diagnostik perencana melalui --trace-plan

Indeks ini tersedia melalui greph-index CLI dan metode facade Greph::buildTextIndex() / Greph::searchTextIndexed().

Membangun indeks

Shell
# Full build at the current directory
./vendor/bin/greph-index build .

# Full build at an explicit root
./vendor/bin/greph-index build path/to/repo

# Use a non-default index directory
./vendor/bin/greph-index build . --index-dir /tmp/greph-index

# Build with an explicit lifecycle policy
./vendor/bin/greph-index build . \
  --lifecycle opportunistic-refresh \
  --auto-refresh-max-files 32 \
  --auto-refresh-max-bytes 1048576

Secara default, indeks disimpan di <root>/.greph-index/.

Build yang berhasil mencetak ringkasan satu baris:

Text
Built index for 2547 files in .greph-index (193428 trigrams, +2547 ~0 -0 =0)

Keempat penghitung tersebut adalah jumlah file yang ditambahkan, diperbarui, dihapus, dan tidak berubah. Pada pembuatan baru, nilai penghitung file yang ditambahkan sama dengan jumlah file, sementara semua penghitung lainnya bernilai nol.

Menyegarkan indeks

Shell
./vendor/bin/greph-index refresh .

refresh menelusuri ulang root yang diindeks, menghitung hash setiap file, dan hanya menulis ulang entri yang metadatanya berubah. Output menggunakan empat penghitung yang sama agar Anda dapat melihat dengan tepat apa yang berubah:

Text
Refreshed index for 2547 files in .greph-index (193428 trigrams, +3 ~7 -1 =2536)

Jalankan refresh setelah mengedit file yang dilacak saat Anda menggunakan manual-refresh. Untuk indeks opportunistic-refresh, Greph dapat menyegarkan indeks secara otomatis selama pencarian jika kumpulan perubahan masih cukup kecil.

Profil siklus hidup

Greph tetap tanpa daemon. Profil siklus hidup mengatur perilaku indeks hangat saat pohon sumber berubah:

  • static: jangan pernah memeriksa kebaruan atau mengubah apa pun secara otomatis
  • manual-refresh: tampilkan informasi usang di stats, tetapi jangan pernah menyegarkan saat pencarian
  • opportunistic-refresh: segarkan saat pencarian hanya jika kumpulan perubahan berada di bawah ambang yang dikonfigurasi
  • strict-stale-check: tolak pencarian hangat yang usang alih-alih menyegarkannya

Gunakan greph-index stats --dry-refresh untuk memeriksa tindakan pencarian hangat sebelum menjalankannya:

Shell
./vendor/bin/greph-index stats . --dry-refresh

Membuat kueri pada indeks

Shell
# Fixed-string search
./vendor/bin/greph-index search -F "function" .

# Case-insensitive whole-word
./vendor/bin/greph-index search -F -i -w "function" .

# Counts
./vendor/bin/greph-index search -F -c "function" .

# Files only
./vendor/bin/greph-index search -F -l "function" .

# Multi-index search
./vendor/bin/greph-index search -F "apply_filters" . \
  --index-dir wordpress/.greph-index \
  --index-dir wp-content/plugins/my-plugin/.greph-index \
  --show-index-origin

# Regex search
./vendor/bin/greph-index search "function\s+\w+" .

# JSON output
./vendor/bin/greph-index search --json -F "function" .

# Planner trace to stderr
./vendor/bin/greph-index search --trace-plan -F "function" .

Set flag-nya sama dengan pencarian teks native. Lihat referensi CLI untuk daftar lengkapnya.

Jika indeks tidak ada di lokasi yang diminta, greph-index search akan menghasilkan error. Perintah ini tidak secara otomatis beralih ke pemindaian nonindeks (perintah AST memiliki opsi --fallback scan, tetapi perintah teks tidak). Buat indeks terlebih dahulu.

Set indeks bernama

Jika Anda berulang kali mencari tata letak hangat yang sama, gunakan manifes alih-alih mengulang flag --index-dir:

JSON
{
  "name": "wordpress-local",
  "indexes": [
    {
      "name": "core-text",
      "root": "wordpress",
      "mode": "text",
      "lifecycle": "static",
      "priority": 100
    },
    {
      "name": "plugin-text",
      "root": "wp-content/plugins/my-plugin",
      "mode": "text",
      "lifecycle": "opportunistic-refresh",
      "max_changed_files": 16,
      "max_changed_bytes": 262144,
      "priority": 200
    }
  ]
}

Simpan sebagai .greph-index-set.json, lalu:

Shell
./vendor/bin/greph-index set build
./vendor/bin/greph-index set stats --dry-refresh
./vendor/bin/greph-index set search --show-index-origin -F "apply_filters" .

Data yang disimpan indeks

Indeks teks adalah penyimpanan trigram + posting pengenal. Untuk setiap file yang diindeks, Greph mengekstrak:

  • Kumpulan trigram: kumpulan urutan tiga byte yang ada dalam konten file. Digunakan sebagai prafilter kasar untuk kueri literal maupun regex.
  • Posting pengenal: kumpulan token berbentuk pengenal ([A-Za-z_][A-Za-z0-9_]*) yang ada dalam file. Digunakan untuk mempercepat kueri kata utuh.
  • Metadata siklus hidup: ambang dan perilaku pemeriksaan data usang yang disimpan.
  • Metadata konten: ukuran dan mtime untuk keputusan penyegaran dan pemeriksaan data usang.

Saat kueri diterima, Greph mengekstrak bentuk yang sama dari pola (trigram dari substring literal, token pengenal dari pola kata utuh), mengiriskan posting, lalu hanya membaca ulang file yang cocok. File yang lolos dari irisan dicari dengan mesin yang sama seperti mode teks native.

Untuk beberapa kueri ringkasan hangat, Greph dapat menjawab langsung dari posting:

  • -l kata utuh
  • -L kata utuh
  • -q kata utuh

Dengan begitu, file kandidat tidak perlu dibuka kembali sama sekali jika posting sudah membuktikan jawabannya.

Gagasannya sama dengan prapengindeksan opsional milik ripgrep dan indeks trigram codesearch, tetapi dibuat khusus untuk bentuk di disk yang dapat dicari paling cepat oleh PHP hangat.

Diagnostik perencana

--trace-plan mengirimkan keputusan perencana teks hangat ke stderr tanpa mengubah aliran hasil normal.

Jejaknya mencakup:

  • profil siklus hidup
  • jumlah file yang dipilih
  • sumber kandidat (full-scan, trigram-postings, word-postings, atau invert-scan)
  • jumlah istilah posting
  • jumlah file kandidat dan yang diverifikasi
  • kelayakan ringkasan langsung
  • kelayakan cache kueri dan keputusan pengisiannya

Kapan menggunakannya

Mode terindeks adalah pilihan tepat saat:

  • Anda mengueri repositori yang sama berkali-kali berturut-turut (pekerjaan CI, loop agen, integrasi IDE).
  • Repositori cukup besar sehingga pemindaian native menjadi hambatan.
  • Pola mencakup substring literal atau token pengenal yang dapat digunakan indeks untuk melakukan prafilter.

Pemindaian native tetap menjadi pilihan tepat saat:

  • Anda mengueri repositori kecil yang biaya pembuatannya lebih besar.
  • Anda mencari jalur satu kali yang tidak akan diku eri lagi.
  • Anda membutuhkan setiap kecocokan dalam satu pemanggilan ad hoc dan tidak ingin memelihara indeks.

Angka tolok ukur yang dipublikasikan di README menunjukkan mode terindeks hangat unggul atas rg dan grep pada kueri regex serta kueri hitungan, file dengan kecocokan, dan file tanpa kecocokan pada korpus WordPress. Pada kueri literal biasa, kinerjanya lebih baik daripada grep, tetapi masih sedikit di bawah rg.

Penggunaan secara terprogram

PHP
use Greph\Greph;
use Greph\Text\TextSearchOptions;
use Greph\Index\IndexLifecycleProfile;

// Build once
Greph::buildTextIndex('.', lifecycle: IndexLifecycleProfile::OpportunisticRefresh);

// Refresh after edits
Greph::refreshTextIndex('.');

// Query
$results = Greph::searchTextIndexed(
    'function',
    'src',
    new TextSearchOptions(fixedString: true),
);

searchTextIndexed menerima TextSearchOptions yang sama dengan pencarian teks native dan mengembalikan bentuk list<TextFileResult> yang sama. Untuk alur dengan beberapa indeks atau yang didukung manifes, gunakan searchTextIndexedMany(...) dan searchTextIndexedSet(...).