
# Consultas

`RecordQuery` es el filtro en flujo que se usa con `stream()`. Abarca los patrones de acceso basados en añadir datos: reanudar desde un cursor, leer un intervalo de tiempo, filtrar por igualdad de campo y detenerse al llegar a un límite. Para predicados más complejos, ordenación y búsquedas respaldadas por índices, use el [constructor de consultas](https://storh.inline0.dev/es/docs/query-builder); para todo lo que puede hacer un `foreach` normal sobre un flujo, `RecordQuery` es la opción más ligera.

`RecordQuery` es inmutable. Cada modificador devuelve una consulta clonada:

```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()` y `time_range_ms()` usan el orden UUID, por lo que no necesitan un campo de marca de tiempo en los datos del registro. En `SegmentedLog` también evitan trabajo: nunca se abren los segmentos cuyo intervalo de identificadores queda fuera del rango, y los índices dispersos por segmento buscan cerca del primer registro coincidente en vez de recorrerlos desde el principio.

`where_equal()` compara un campo de datos de nivel superior con `===` y acepta valores escalares o `null`. Un filtro `null` coincide con los registros donde el campo está presente y es nulo; los registros que no tienen el campo no coinciden.

## Paginación con cursores

Los identificadores se ordenan por hora de creación, así que el último identificador de una página sirve de cursor para la siguiente:

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

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

## Cómo conservar los registros dañados

De forma predeterminada, un recorrido falla al encontrar el primer registro ilegible. Use `continue_on_error()` si el recorrido debe omitirlo e informar del error:

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

La ubicación es el identificador del registro para `DocStore` y `segment-file:byte-offset` para `SegmentedLog`. `repair()` sirve para limpiar los registros dañados; consulte [CLI](https://storh.inline0.dev/es/docs/cli).
