
# Indexované vyhľadávanie textu

Indexované vyhľadávanie textu je verzia [vyhľadávania textu](https://greph.inline0.dev/sk/docs/modes/text) s prednačítanou cache. Prvé volanie vytvorí úložisko trigramov a výskytov identifikátorov na disku; ďalšie volania ho používajú na preskočenie súborov, ktoré zjavne nemôžu obsahovať vzor. Výsledkom je výrazne nižšia latencia pri opakovaných vyhľadávaniach vo veľkých repozitároch bez potreby démona alebo procesu sledovania zmien.

Prednačítané textové vyhľadávanie teraz zahŕňa:

- vyhľadávanie v jednom indexe
- opakované vyhľadávanie vo viacerých indexoch `--index-dir`
- vyhľadávanie v množinách podložených manifestom
- spracovanie zastaraných údajov zohľadňujúce životný cyklus
- diagnostiku plánovača cez `--trace-plan`

Index je štandardne dostupný cez `greph-index` CLI a metódy fasády `Greph::buildTextIndex()` / `Greph::searchTextIndexed()`.

## Zostavenie indexu

```bash
# 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
```

Index sa štandardne ukladá do `<root>/.greph-index/`.

Úspešné zostavenie vypíše súhrn v jednom riadku:

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

Štyri počítadlá uvádzajú počet pridaných, aktualizovaných, odstránených a nezmenených súborov. Pri novom zostavení sa počítadlo pridaných rovná počtu súborov a všetky ostatné majú hodnotu nula.

## Obnovenie indexu

```bash
./vendor/bin/greph-index refresh .
```

`refresh` znova prejde indexovaný koreňový adresár, vypočíta hash každého súboru a prepíše iba položky, ktorých metadáta sa zmenili. Výstup používa tie isté štyri počítadlá, aby ste presne videli, čo sa zmenilo:

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

Po úprave sledovaných súborov spustite `refresh`, ak používate `manual-refresh`. Pri indexoch `opportunistic-refresh` môže Greph automaticky obnoviť index počas vyhľadávania, ak je množina zmien stále dostatočne malá.

## Profily životného cyklu

Greph funguje bez démona. Profily životného cyklu určujú, ako sa prednačítaný index správa pri zmene zdrojového stromu:

- `static`: nikdy automaticky nekontrolovať aktuálnosť ani nič nemeniť
- `manual-refresh`: uvádzať zastarané informácie v `stats`, ale počas vyhľadávania nikdy neobnovovať
- `opportunistic-refresh`: obnovovať počas vyhľadávania iba vtedy, keď je množina zmien pod nakonfigurovanými limitmi
- `strict-stale-check`: odmietnuť zastarané vyhľadávania v prednačítanom indexe namiesto obnovovania

Pomocou `greph-index stats --dry-refresh` si pred spustením vyhľadávania prezrite, čo by prednačítané vyhľadávanie vykonalo:

```bash
./vendor/bin/greph-index stats . --dry-refresh
```

## Vyhľadávanie v indexe

```bash
# 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" .
```

Množina príznakov je rovnaká ako pri natívnom vyhľadávaní textu. Úplný zoznam nájdete v [CLIreferenčnej príručke](https://greph.inline0.dev/sk/docs/cli#greph-index).

Ak index na požadovanom mieste neexistuje, `greph-index search` vyvolá chybu. Tento príkaz automaticky neprechádza na prehľadávanie bez indexu (príkazy AST majú voliteľný parameter `--fallback scan`, textový príkaz ho však nemá). Najprv zostavte index.

## Pomenované množiny indexov

Ak opakovane vyhľadávate v rovnakom prednačítanom usporiadaní, použite manifest namiesto opakovania príznakov `--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
    }
  ]
}
```

Uložte ho ako `.greph-index-set.json` a potom:

```bash
./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" .
```

## Čo index ukladá

Textový index je úložisko trigramov a výskytov identifikátorov. Pre každý indexovaný súbor Greph získava:

- **Množina trigramov**: množina trojíc bajtov v obsahu súboru. Používa sa ako hrubý predbežný filter pre doslovné vyhľadávanie aj vyhľadávanie regulárnymi výrazmi.
- **Výskyty identifikátorov**: množina tokenov v tvare identifikátorov (`[A-Za-z_][A-Za-z0-9_]*`) v súbore. Používa sa na zrýchlenie vyhľadávania celých slov.
- **Metadáta životného cyklu**: uložené limity a správanie pri kontrole zastaranosti.
- **Metadáta obsahu**: veľkosť a čas poslednej úpravy na rozhodovanie o obnovení a kontrolu zastaranosti.

Po prijatí dopytu Greph získa rovnaké tvary zo vzoru (trigramy z doslovných podreťazcov, tokeny identifikátorov zo vzorov celých slov), pretne množiny výskytov a znova načíta iba zodpovedajúce súbory. Súbory, ktoré prejdú prienikom, sa vyhľadajú rovnakým nástrojom ako v natívnom textovom režime.

Pri niektorých súhrnných dopytoch v prednačítanom režime môže Greph odpovedať priamo z výskytov:

- celé slovo `-l`
- celé slovo `-L`
- celé slovo `-q`

Vďaka tomu sa kandidátne súbory vôbec nemusia znova otvárať, ak už výskyty dokazujú odpoveď.

Je to rovnaký princíp ako voliteľné predindexovanie v ripgrep a trigramový index v codesearch, zostavený však špeciálne pre tvary na disku, ktoré prednačítaný PHP dokáže spracovať najrýchlejšie.

## Diagnostika plánovača

`--trace-plan` odovzdáva rozhodnutie plánovača prednačítaného textového vyhľadávania do `stderr` a pritom nemení bežný prúd výsledkov.

Záznam obsahuje:

- profil životného cyklu
- počet vybraných súborov
- zdroj kandidátov (`full-scan`, `trigram-postings`, `word-postings` alebo `invert-scan`)
- počet výrazov vo výskytoch
- počet kandidátnych a overených súborov
- oprávnenosť na priame vytvorenie súhrnu
- oprávnenosť použitia cache dopytov a rozhodnutie o jej naplnení

## Kedy ho použiť

Indexovaný režim je vhodný, keď:

- Vyhľadávate v tom istom repozitári opakovane (úlohy CI, cykly agentov, integrácie IDE).
- Repozitár je natoľko veľký, že úzkym miestom je natívne prehľadávanie.
- Vzory obsahujú doslovné podreťazce alebo tokeny identifikátorov, podľa ktorých môže index filtrovať.

Natívne prehľadávanie je stále vhodné, keď:

- Vyhľadávate v malom repozitári, kde prevažujú náklady na zostavenie indexu.
- Vyhľadávate v jednorazovej ceste, ktorú už znova prehľadávať nebudete.
- Potrebujete všetky zhody pri jednom príležitostnom spustení a nechcete udržiavať index.

Zverejnené výsledky porovnávacích testov v [README](https://github.com/inline0/greph#performance) ukazujú, že prednačítaný indexovaný režim je pri dopytoch s regulárnymi výrazmi a pri dopytoch na počet, súbory so zhodami a súbory bez zhôd v korpuse WordPress rýchlejší než `rg` aj `grep`. Pri dopytoch s jednoduchým doslovným textom je rýchlejší než `grep`, ale zostáva mierne pomalší než `rg`.

## Programové použitie

```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` prijíma rovnaké `TextSearchOptions` ako natívne vyhľadávanie textu a vracia výsledok v rovnakom tvare `list<TextFileResult>`. Pri práci s viacerými indexmi alebo manifestom použite `searchTextIndexedMany(...)` a `searchTextIndexedSet(...)`.
