Gå til indhold

Indekseret tekstsøgning

Indekseret tekstsøgning er den version af tekstsøgning, der udnytter en opvarmet cache. Det første kald opbygger et lager på disken med trigrammer og identifier-posteringer; efterfølgende kald bruger lageret til at springe filer over, som tydeligvis ikke kan indeholde mønsteret. Resultatet er markant lavere latenstid ved gentagne forespørgsler i store repositories uden at indføre en daemon- eller watcher-proces.

Den opvarmede tekstfunktion omfatter nu:

  • Søgning i ét indeks
  • Gentagen søgning i --index-dir flere indeks
  • Søgning i sæt baseret på manifest
  • Håndtering af forældede data med kendskab til livscyklussen
  • Planlægningsdiagnostik via --trace-plan

Indekset er tilgængeligt via greph-index CLI og facadefunktionerne Greph::buildTextIndex() / Greph::searchTextIndexed().

Oprettelse af indekset

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

Indekset gemmes som standard på <root>/.greph-index/.

En vellykket oprettelse udskriver en oversigt på én linje:

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

De fire tællere viser antal tilføjede, opdaterede, slettede og uændrede filer. Ved en ny opbygning svarer tælleren for tilføjede til filantallet, og alle andre tællere er nul.

Opdatering af indekset

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

refresh gennemgår det indekserede rodområde igen, hasher hver fil og omskriver kun poster, hvis metadata er ændret. Resultatet bruger de samme fire tællere, så du kan se præcis, hvad der har ændret sig:

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

Kør refresh efter redigering af sporede filer, når du bruger manual-refresh. For indeks af typen opportunistic-refresh kan Greph opdatere indekset automatisk under søgning, hvis mængden af ændringer stadig er lille nok.

Livscyklusprofiler

Greph kræver ingen dæmon. Livscyklusprofiler styrer, hvordan et opvarmet indeks opfører sig, når kildetræet ændres:

  • static: kontrollér aldrig aktualitet, og foretag aldrig automatiske ændringer
  • manual-refresh: vis oplysninger om forældede data i stats, men opdatér aldrig under søgning
  • opportunistic-refresh: opdatér under søgning, men kun hvis mængden af ændringer er under de konfigurerede tærskler
  • strict-stale-check: afvis forældede søgninger i det opvarmede indeks i stedet for at opdatere

Brug greph-index stats --dry-refresh til at se, hvad opvarmet søgning ville gøre, før du kører den:

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

Forespørgsler i indekset

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

Flagsættet er det samme som ved indbygget tekstsøgning. Se CLI-referencen for den fulde liste.

Hvis indekset ikke findes på den angivne placering, udløser greph-index search en fejl. Denne kommando falder ikke automatisk tilbage til en søgning uden indeks (AST-kommandoerne har et valgfrit --fallback scan, men tekstkommandoen har ikke). Byg indekset først.

Navngivne indekssæt

Hvis du gentagne gange søger i det samme opvarmede layout, kan du bruge et manifest i stedet for at gentage --index-dir-flagene:

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

Gem det som .greph-index-set.json, og kør derefter:

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

Hvad indekset gemmer

Tekstindekset er et lager med trigrammer og identifikatorforekomster. For hver indekseret fil udtrækker Greph:

  • Trigrammængde: mængden af sekvenser på tre byte, der findes i filindholdet. Bruges som et groft forfilter til både bogstavelige forespørgsler og regex-forespørgsler.
  • Identifikatorforekomster: mængden af identifikatorlignende tokens ([A-Za-z_][A-Za-z0-9_]*) i filen. Bruges til at accelerere søgninger efter hele ord.
  • Livscyklusmetadata: gemte tærskler og adfærd ved kontrol af forældede data.
  • Indholdsmetadata: størrelse og mtime til beslutninger om opdatering og inspektion af forældede data.

Når en forespørgsel kommer, udtrækker Greph de samme former fra mønsteret (trigrammer fra bogstavelige delstrenge og identifikatortokens fra mønstre for hele ord), skærer forekomsterne ned til fælles resultater og genlæser kun de matchende filer. Filer, der består denne filtrering, søges igennem med samme motor som i den indbyggede teksttilstand.

For nogle opvarmede oversigtsforespørgsler kan Greph svare direkte ud fra forekomsterne:

  • -l for hele ord
  • -L for hele ord
  • -q for hele ord

Så behøver kandidatfilerne slet ikke blive åbnet igen, når forekomsterne allerede beviser svaret.

Det er samme idé som valgfri forindeksering i ripgrep og trigramindekset i codesearch, men bygget specifikt omkring de former på disken, som opvarmet PHP hurtigst kan ramme.

Planlægningsdiagnostik

--trace-plan sender beslutningen fra planlæggeren for opvarmet tekst til stderr, mens den normale resultatstrøm forbliver uændret.

Sporet omfatter:

  • Livscyklusprofil
  • Antal valgte filer
  • Kandidatkilde (full-scan, trigram-postings, word-postings eller invert-scan)
  • Antal forekomsttermer
  • Antal kandidatfiler og verificerede filer
  • Om direkte oversigtsresultater er mulige
  • Om forespørgselscache er mulig, og beslutning om indlæsning

Hvornår skal den bruges

Indekseret tilstand er det rette værktøj, når:

  • Du forespørger i det samme arkiv mange gange i træk (CI-job, agentløkker, IDE-integrationer).
  • Arkivet er så stort, at indbygget scanning er flaskehalsen.
  • Mønstrene indeholder bogstavelige delstrenge eller identifikatortokens, som indekset kan forfiltrere efter.

Indbygget scanning er stadig det rette værktøj, når:

  • Du forespørger i et lille arkiv, hvor omkostningen ved opbygning dominerer.
  • Du søger i en enkelt sti, som du ikke vil søge i igen.
  • Du har brug for alle match i én enkeltstående forespørgsel og ikke vil vedligeholde et indeks.

De offentliggjorte benchmarktal i README viser, at den opvarmede indekserede tilstand klarer sig bedre end både rg og grep ved regex-forespørgsler og forespørgsler efter antal, filer med match og filer uden match i WordPress-korpusset. Ved almindelige bogstavelige forespørgsler slår den grep, men er stadig en smule langsommere end rg.

Programmatisk brug

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 accepterer de samme TextSearchOptions som indbygget tekstsøgning og returnerer samme list<TextFileResult>-struktur. Brug searchTextIndexedMany(...) og searchTextIndexedSet(...) til forløb med flere indeks eller manifestunderstøttelse.