
# Generatore di query

`DocStore` e `SegmentedLog` espongono `query()`. `DocStore` può usare indici secondari; `SegmentedLog` applica gli stessi predicati ai record trasmessi in streaming.

```php
$records = $docs
    ->query()
    ->where('kind')->eq('page')
    ->where('status')->in(['draft', 'published'])
    ->where('publishedAt')->between($from, $until)
    ->orderBy('publishedAt', 'desc')
    ->limit(50)
    ->get();
```

Metodi terminali utili:

```php
$docs->query()->where('slug')->eq('home')->first();
$docs->query()->where('kind')->eq('page')->count();
$docs->query()->cursor($lastId)->page(100)->get();
$docs->query()->where('slug')->eq('home')->explain();
```

Su `DocStore`, due condizioni `eq` su campi indicizzati per uguaglianza non univoci possono usare un bucket composto automatico. Le condizioni di uguaglianza singole, `in` e gli operatori per intervallo continuano a usare gli indici configurati per i campi.

Operatori:

- `eq`, `neq`
- `in`, `notIn`
- `gt`, `gte`, `lt`, `lte`, `between`
- `exists`, `missing`
- `prefix`
- `andWhere`, `orWhere`
- `orderBy`, `limit`, `cursor`, `page`

`andWhere` e `orWhere` usano callback perché `and` e `or` sono parole chiave riservate PHP:

```php
$docs->query()
    ->where('kind')->eq('page')
    ->orWhere(fn ($q) => $q->where('kind')->eq('post')->where('featured')->eq(true))
    ->get();
```

Le chiamate concatenate a `where()` si combinano con AND; ogni ramo `orWhere()` aggiunge un'alternativa.

## Modalità di esecuzione

Ogni condizione funziona su ogni raccolta; gli indici cambiano solo il costo.
Su `DocStore`, `eq` e `in` vengono risolti tramite indici di uguaglianza, gli operatori per intervallo e `prefix` tramite indici per intervallo, mentre `orderBy` con `limit` su un campo indicizzato per intervallo legge seguendo l'ordine dell'indice. Tutto il resto filtra una scansione dei record. `orderBy` su un campo che il pianificatore non può servire tramite un indice ordina i record corrispondenti in PHP; perciò, sulle raccolte grandi, abbinatelo a condizioni indicizzate. `count()` usa il numero di voci dell'indice su `DocStore` e i contatori in memoria su `SegmentedLog` quando il filtro è una singola uguaglianza.

`cursor($id)` limita i risultati ai record successivi all'ID, e si combina con `page()` per una paginazione stabile ordinata per ID del record. Per filtri in streaming semplici senza il generatore, consultate [Query](https://storh.inline0.dev/it/docs/queries).
