Ga naar de inhoud

Geïndexeerd zoeken in tekst

Geïndexeerd zoeken in tekst is de variant van zoeken in tekst met een opgewarmde cache. Bij de eerste aanroep wordt op schijf een opslag met trigrammen en identifier-vermeldingen aangemaakt; bij volgende aanroepen wordt die opslag gebruikt om bestanden over te slaan die het patroon duidelijk niet kunnen bevatten. Zo wordt de latentie bij herhaalde queries in grote repositories veel lager, zonder een daemon- of watcherproces toe te voegen.

Het aanbod voor zoeken in tekst met een opgewarmde cache omvat nu:

  • zoeken in één index
  • herhaald zoeken in --index-dir meerdere indexen
  • zoeken in een set op basis van een manifest
  • afhandeling van verouderde gegevens met inzicht in de levenscyclus
  • plannerdiagnostiek via --trace-plan

De index is beschikbaar via de greph-index CLI en de facade-methoden Greph::buildTextIndex() / Greph::searchTextIndexed().

De index bouwen

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

De index wordt standaard opgeslagen op <root>/.greph-index/.

Na een geslaagde build wordt een samenvatting van één regel weergegeven:

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

De vier tellers geven het aantal toegevoegde, bijgewerkte, verwijderde en ongewijzigde bestanden weer. Bij een nieuwe build is de teller voor toegevoegde bestanden gelijk aan het aantal bestanden en staan alle andere tellers op nul.

De index vernieuwen

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

refresh doorloopt de geïndexeerde hoofdmap opnieuw, hasht elk bestand en herschrijft alleen de vermeldingen waarvan de metadata is gewijzigd. De uitvoer gebruikt dezelfde vier tellers, zodat je precies kunt zien wat er is veranderd:

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

Voer refresh uit nadat je bijgehouden bestanden hebt bewerkt wanneer je manual-refresh gebruikt. Voor indexen van opportunistic-refresh kan Greph de index automatisch vernieuwen tijdens het zoeken, zolang de verzameling gewijzigde bestanden klein genoeg is.

Levenscyclusprofielen

Greph blijft daemonvrij. Levenscyclusprofielen bepalen hoe een opgewarmde index zich gedraagt wanneer de bronstructuur verandert:

  • static: controleer nooit automatisch of de gegevens actueel zijn en wijzig ze niet automatisch
  • manual-refresh: geef verouderde informatie weer in stats, maar vernieuw nooit tijdens het zoeken
  • opportunistic-refresh: vernieuw tijdens het zoeken alleen als de verzameling gewijzigde bestanden onder de ingestelde drempelwaarden blijft
  • strict-stale-check: wijs verouderde zoekopdrachten met een opgewarmde cache af in plaats van de cache te vernieuwen

Gebruik greph-index stats --dry-refresh om te bekijken wat zoeken met een opgewarmde cache zou doen voordat je het uitvoert:

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

De index doorzoeken

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" .

De set vlaggen is hetzelfde als bij native zoeken in tekst. Raadpleeg de CLIreferentie voor de volledige lijst.

Als de index niet bestaat op de opgegeven locatie, geeft greph-index search een foutmelding. Deze opdracht schakelt niet automatisch over op een niet-geïndexeerde scan (de AST-opdrachten hebben een optionele --fallback scan, maar de tekstopdracht niet). Bouw eerst de index.

Benoemde indexsets

Als je herhaaldelijk dezelfde opgewarmde indeling doorzoekt, gebruik dan een manifest in plaats van telkens de vlaggen --index-dir opnieuw op te geven:

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
    }
  ]
}

Sla het op als .greph-index-set.json en voer daarna uit:

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" .

Wat de index opslaat

De tekstindex is een opslag met trigrammen en identifier-vermeldingen. Voor elk geïndexeerd bestand haalt Greph het volgende op:

  • Trigrammenset: de set van reeksen van drie bytes die in de bestandsinhoud voorkomen. Wordt gebruikt als grove voorfilter voor zowel letterlijke als regex-queries.
  • Identifier-vermeldingen: de set van tokens in identifier-vorm ([A-Za-z_][A-Za-z0-9_]*) die in het bestand voorkomen. Wordt gebruikt om zoekopdrachten naar hele woorden te versnellen.
  • Levenscyclusmetadata: opgeslagen drempelwaarden en gedrag bij verouderde gegevens.
  • Inhoudsmetadata: grootte en mtime voor beslissingen over vernieuwen en inspectie van verouderde gegevens.

Wanneer een query binnenkomt, haalt Greph dezelfde vormen uit het patroon (trigrammen uit letterlijke deelreeksen, identificertokens uit patronen voor hele woorden), snijdt de vermeldingen met elkaar en leest alleen de overeenkomende bestanden opnieuw. Bestanden die deze doorsnede doorstaan, worden doorzocht met dezelfde engine als de native tekstmodus.

Voor sommige samenvattingsqueries met een opgewarmde cache kan Greph rechtstreeks antwoorden op basis van de vermeldingen:

  • hele woorden -l
  • hele woorden -L
  • hele woorden -q

Zo hoeven kandidaatbestanden helemaal niet opnieuw te worden geopend wanneer de vermeldingen het antwoord al bewijzen.

Dit is hetzelfde idee als de optionele pre-indexering van ripgrep en de trigramindex van codesearch, maar speciaal gebouwd rond de vormen op schijf die zoeken met een opgewarmde PHP het snelst kan doorzoeken.

Plannerevaluatie

--trace-plan schrijft de beslissing van de tekstplanner met opgewarmde cache naar stderr en laat de normale resultaatstroom ongemoeid.

De trace bevat:

  • levenscyclusprofiel
  • aantal geselecteerde bestanden
  • kandidaatbron (full-scan, trigram-postings, word-postings of invert-scan)
  • aantal termen in vermeldingen
  • aantal kandidaatbestanden en geverifieerde bestanden
  • geschiktheid voor een directe samenvatting
  • geschiktheid voor de querycache en de beslissing om die te vullen

Wanneer gebruik je deze?

De geïndexeerde modus is de juiste keuze wanneer:

  • Je dezelfde repository vaak achter elkaar doorzoekt (CI-taken, agentloops, IDE-integraties).
  • De repository groot genoeg is om native scannen tot de bottleneck te maken.
  • De patronen letterlijke deelreeksen of identificertokens bevatten waarop de index vooraf kan filteren.

Native scannen is nog steeds de juiste keuze wanneer:

  • Je een kleine repository doorzoekt, waar de bouwkosten overheersen.
  • Je een eenmalig pad doorzoekt dat je niet opnieuw zult doorzoeken.
  • Je alle matches in één ad-hoc-aanroep nodig hebt en geen index wilt onderhouden.

De gepubliceerde benchmarkcijfers in de README laten zien dat de geïndexeerde modus met opgewarmde cache beter presteert dan zowel rg als grep bij regex-queries en bij queries naar aantallen, bestanden met matches en bestanden zonder matches op het WordPress-corpus. Bij gewone letterlijke queries is deze modus sneller dan grep, maar blijft hij iets achter bij rg.

Programmatisch gebruik

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 accepteert dezelfde TextSearchOptions als native zoeken in tekst en retourneert dezelfde list<TextFileResult>-vorm. Gebruik voor flows met meerdere indexen of op basis van een manifest searchTextIndexedMany(...) en searchTextIndexedSet(...).