
# Dizinlenmiş Metin Araması

Dizinlenmiş metin araması, [metin araması](https://greph.inline0.dev/tr/docs/modes/text)nın ısıtılmış önbellekli sürümüdür. İlk çağrı, trigramlardan ve tanımlayıcı gönderimlerinden oluşan bir disk deposu oluşturur; sonraki çağrılar, örüntüyü içermesi açıkça mümkün olmayan dosyaları atlamak için bu depoyu kullanır. Böylece arka plan hizmeti veya izleyici süreci çalıştırmadan, büyük depolardaki yinelenen sorguların gecikmesi önemli ölçüde azalır.

Isıtılmış metin özellikleri artık şunları içeriyor:

- Tek dizinde arama
- Tekrarlanan `--index-dir` çoklu dizin araması
- Bildirim dosyası destekli küme araması
- Yaşam döngüsünü dikkate alan eskilik yönetimi
- `--trace-plan` üzerinden planlayıcı tanılamaları

Dizine `greph-index` CLI alt komutundan ve `Greph::buildTextIndex()` / `Greph::searchTextIndexed()` arayüz yöntemlerinden erişilir.

## Dizini oluşturma

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

Dizin varsayılan olarak `<root>/.greph-index/` konumunda saklanır.

Başarılı bir oluşturma işlemi tek satırlık bir özet yazdırır:

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

Dört sayaç, eklenen, güncellenen, silinen ve değişmeden kalan dosyaların sayısını gösterir. Yeni bir dizin oluşturulduğunda eklenen sayacı dosya sayısına eşit, diğerleri ise sıfırdır.

## Dizini yenileme

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

`refresh` dizinlenen kökü yeniden tarar, her dosyanın karmasını hesaplar ve yalnızca üst verisi değişen girdileri yeniden yazar. Çıktıda, nelerin değiştiğini tam olarak görebilmeniz için aynı dört sayaç kullanılır:

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

`manual-refresh` kullanırken izlenen dosyaları düzenledikten sonra `refresh` komutunu çalıştırın. `opportunistic-refresh` dizinlerinde, değişen küme hâlâ yeterince küçükse Greph arama sırasında dizini otomatik olarak yenileyebilir.

## Yaşam döngüsü profilleri

Greph arka plan hizmeti çalıştırmaz. Yaşam döngüsü profilleri, kaynak ağacı değiştiğinde ısıtılmış dizinin nasıl davranacağını belirler:

- `static`: güncelliği hiçbir zaman denetleme veya otomatik olarak değiştirme
- `manual-refresh`: eski bilgileri `stats` içinde göster, ancak arama sırasında hiçbir zaman yenileme
- `opportunistic-refresh`: yalnızca değişen küme yapılandırılan eşiklerin altındaysa arama sırasında yenile
- `strict-stale-check`: eski ısıtılmış aramaları yenilemek yerine reddet

Isıtılmış aramanın çalıştırılmadan önce ne yapacağını incelemek için `greph-index stats --dry-refresh` kullanın:

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

## Dizinde sorgu yapma

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

Seçenek kümesi yerel metin aramasıyla aynıdır. Tüm seçenekler için [CLIbaşvuru](https://greph.inline0.dev/tr/docs/cli#greph-index) bölümüne bakın.

İstenen konumda dizin yoksa `greph-index search` hata verir. Bu komut, dizinlenmemiş bir taramaya otomatik olarak geçmez (AST komutlarında isteğe bağlı bir `--fallback scan` vardır, ancak metin komutunda yoktur). Önce dizini oluşturun.

## Adlandırılmış dizin kümeleri

Aynı ısıtılmış düzende tekrar tekrar arama yapıyorsanız, `--index-dir` seçeneklerini yinelemek yerine bir bildirim dosyası kullanın:

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

Dosyayı `.greph-index-set.json` adıyla kaydedin, ardından:

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

## Dizinin sakladıkları

Metin dizini, trigram + tanımlayıcı gönderimlerinden oluşan bir depodur. Greph, dizinlenen her dosya için şunları çıkarır:

- **Trigram kümesi**: Dosya içeriğinde bulunan üç baytlık dizilerin kümesi. Hem düz metin hem de regex sorguları için genel bir ön filtre olarak kullanılır.
- **Tanımlayıcı gönderimleri**: Dosyada bulunan tanımlayıcı biçimindeki belirteçlerin (`[A-Za-z_][A-Za-z0-9_]*`) kümesi. Tam sözcük sorgularını hızlandırmak için kullanılır.
- **Yaşam döngüsü üst verileri**: Saklanan eşikler ve eski veri denetimi davranışı.
- **İçerik üst verileri**: Yenileme kararları ve eskilik incelemesi için boyut ve mtime.

Bir sorgu geldiğinde Greph, örüntüdeki aynı yapıları çıkarır (düz metin alt dizelerinden trigramları, tam sözcük örüntülerinden tanımlayıcı belirteçlerini), gönderimlerin kesişimini alır ve yalnızca eşleşen dosyaları yeniden okur. Kesişimden geçen dosyalarda, yerel metin moduyla aynı altyapı kullanılarak arama yapılır.

Bazı ısıtılmış özet sorgularında Greph yanıtı doğrudan gönderimlerden verebilir:

- Tam sözcük `-l`
- Tam sözcük `-L`
- Tam sözcük `-q`

Gönderimler yanıtı zaten kanıtlıyorsa bu sayede aday dosyaları yeniden açmak gerekmez.

Bu, ripgrep için isteğe bağlı ön dizinleme ve codesearch'ün trigram diziniyle aynı fikirdir; ancak özellikle ısıtılmış PHP aramalarının en hızlı kullanabildiği disk yapıları için oluşturulmuştur.

## Planlayıcı tanılamaları

`--trace-plan`, normal sonuç akışını değiştirmeden ısıtılmış metin planlayıcısının kararını `stderr` konumuna yazar.

İz şunları içerir:

- Yaşam döngüsü profili
- Seçilen dosya sayısı
- Aday kaynağı (`full-scan`, `trigram-postings`, `word-postings` veya `invert-scan`)
- Gönderim terimi sayısı
- Aday ve doğrulanan dosya sayıları
- Doğrudan özet için uygunluk
- Sorgu önbelleği için uygunluk ve doldurma kararı

## Ne zaman kullanılır?

Dizinli mod şu durumlarda doğru araçtır:

- Aynı depoda art arda birçok kez sorgu çalıştırıyorsanız (CI işleri, ajan döngüleri, IDE entegrasyonları).
- Depo, yerel taramanın darboğaz oluşturacağı kadar büyükse.
- Desenler, dizinin ön eleme yapabileceği sabit alt dizeler veya tanımlayıcı belirteçleri içeriyorsa.

Yerel tarama şu durumlarda hâlâ doğru araçtır:

- Derleme maliyetinin baskın olduğu küçük bir depoda sorgu çalıştırıyorsanız.
- Yeniden sorgulamayacağınız tek seferlik bir yolu arıyorsanız.
- Tek bir özel çağrıda tüm eşleşmelere ihtiyaç duyuyor ve dizin tutmak istemiyorsanız.

[README](https://github.com/inline0/greph#performance) içinde yayımlanan kıyaslama sonuçları, ısıtılmış dizinli modun regex sorgularında ve WordPress derlemi üzerinde sayım, eşleşme içeren dosyalar ve eşleşme içermeyen dosyalar sorgularında hem `rg` hem de `grep`'ten daha iyi olduğunu gösteriyor. Düz sabit dizeli sorgularda `grep`'i geçiyor, ancak `rg`'nin biraz gerisinde kalıyor.

## Programatik kullanım

```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`, yerel metin aramayla aynı `TextSearchOptions` değerlerini kabul eder ve aynı `list<TextFileResult>` yapısını döndürür. Çok dizinli veya bildirim destekli iş akışlarında `searchTextIndexedMany(...)` ve `searchTextIndexedSet(...)` kullanın.
