
# Requêtes

`RecordQuery` est le filtre en continu utilisé avec `stream()`. Il couvre les modes d’accès axés sur les ajouts : reprendre après un curseur, lire une fenêtre temporelle, filtrer par égalité sur un champ et s’arrêter à une limite. Pour des prédicats plus riches, le tri et les recherches avec index, utilisez le [constructeur de requêtes](https://storh.inline0.dev/fr/docs/query-builder) ; pour tout ce qu’un `foreach` classique peut faire sur un flux, `RecordQuery` est l’outil le plus léger.

`RecordQuery` est immuable. Chaque modificateur renvoie une requête clonée :

```php
$query = Storh\RecordQuery::all()
    ->after($lastSeenId)
    ->time_range_ms($fromMs, $untilMs)
    ->where_equal('kind', 'page')
    ->limit(100);

foreach ($store->stream($query) as $record) {
    // Records are yielded lazily.
}
```

`after()` et `time_range_ms()` utilisent l’ordre UUID ; aucun champ d’horodatage n’est donc nécessaire dans les données de l’enregistrement. Sur `SegmentedLog`, ils évitent aussi du travail : les segments dont la plage d’identifiants est hors fenêtre ne sont jamais ouverts, et les index clairsemés par segment permettent d’accéder près du premier enregistrement correspondant au lieu de parcourir les données depuis le début.

`where_equal()` compare un champ de données de premier niveau à `===` et accepte des valeurs scalaires ou `null`. Un filtre `null` correspond aux enregistrements où le champ est présent et vaut null ; les enregistrements sans ce champ ne correspondent pas.

## Pagination par curseur

Les identifiants sont triés par heure de création ; le dernier identifiant d’une page sert donc de curseur pour la suivante :

```php
$page = iterator_to_array($store->stream(
    Storh\RecordQuery::all()->after($lastSeenId)->limit(100)
), false);

$lastSeenId = [] === $page ? $lastSeenId : end($page)->id();
```

## Conserver les enregistrements corrompus

Par défaut, un parcours s’interrompt à la première lecture d’un enregistrement illisible. Utilisez `continue_on_error()` si le parcours doit l’ignorer et signaler l’échec à la place :

```php
$query = Storh\RecordQuery::all()->continue_on_error(
    static function (string $location, Throwable $error): void {
        error_log($location . ': ' . $error->getMessage());
    },
);
```

L’emplacement correspond à l’ID d’enregistrement de `DocStore` et `segment-file:byte-offset` pour `SegmentedLog`. `repair()` est l’outil qui permet de nettoyer les enregistrements corrompus ; voir [CLI](https://storh.inline0.dev/fr/docs/cli).
