
# Indizes

`DocStore`-Indizes werden neben der Sammlung unter `.storh/indexes` gespeichert. Es sind gewöhnliche Dateien, die vollständig aus den Datensätzen abgeleitet werden und jederzeit neu erstellt werden können. Du kannst sie direkt oder über ein [Schema](https://storh.inline0.dev/de/docs/schema) deklarieren:

```php
$docs->indexes()
    ->field('slug')->unique()
    ->field('kind')
    ->field('publishedAt')->range()
    ->sync();
```

Indextypen:

- Gleichheitsindizes für Felder wie `kind` oder `status`: eine Datei pro eindeutigem Wert, sodass eine gezielte Abfrage nur die passende Wertedatei liest
- Eindeutigkeitsindizes für Felder wie `slug`: werden beim Schreiben durchgesetzt; bei doppelten Werten schlägt `put()` fehl, bevor etwas geschrieben wird
- Bereichsindizes für skalare Werte: eine sortierte Datei mit sparsamen Sprungmarken für `gt`, `gte`, `lt`, `lte`, `between` und `prefix`

Bereichsindizes können für dasselbe Feld auch `orderBy` mit einem `limit` direkt in aufsteigender oder absteigender Indexreihenfolge beantworten, ohne das gesamte Ergebnis zu materialisieren und zu sortieren.

Wenn eine Abfrage zwei `eq`-Bedingungen für nicht eindeutige, gleichheitsindizierte Felder kombiniert, kann storh automatisch einen gemeinsamen Bucket für dieses Feldpaar verwenden. So bleiben gezielte Filter über zwei Felder schnell, ohne dass ein zusätzlicher Index deklariert werden muss.

## Konsistenz und Reparatur

Schreibvorgänge aktualisieren Indexeinträge nach dem atomaren Ersetzen der Datensatzdatei unter der Schreibsperre der Sammlung, sodass Datensätze und Indizes gemeinsam aktualisiert werden. `verify()` vergleicht jeden Index mit einem vollständigen Scan der Datensätze und meldet Abweichungen; `reindex()` erstellt alle konfigurierten Indizes anhand der Datensatzdateien neu; `repair()` verschiebt beschädigte Datensätze in Quarantäne und erstellt anschließend die Indizes neu.

```php
$docs->reindex();

$plan = $docs
    ->query()
    ->where('slug')->eq('home')
    ->explain();
```

`explain()` gibt `index_scan` zurück, wenn der Planer einen konfigurierten Index verwenden kann, und andernfalls `full_scan`.
