
# Querybuilder

`DocStore` en `SegmentedLog` bieden `query()`. `DocStore` kan secundaire indexen gebruiken; `SegmentedLog` past dezelfde predicaten toe op gestreamde records.

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

Handige terminalmethoden:

```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();
```

Op `DocStore` kunnen twee `eq`-voorwaarden op velden met een niet-unieke gelijkheidsindex een automatische samengestelde bucket gebruiken. Enkelvoudige gelijkheid, `in` en bereikoperatoren blijven hun geconfigureerde veldindexen gebruiken.

Operatoren:

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

`andWhere` en `orWhere` gebruiken callbacks omdat `and` en `or` gereserveerde PHP-trefwoorden zijn:

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

Aaneengeschakelde aanroepen van `where()` worden gecombineerd met AND; elke `orWhere()`-vertakking voegt een alternatief toe.

## Hoe bewerkingen worden uitgevoerd

Elke voorwaarde werkt op elke collectie; indexen veranderen alleen de kosten. Op `DocStore` worden `eq` en `in` afgehandeld met gelijkheidsindexen, de bereikoperatoren en `prefix` met bereikindexen, en leest `orderBy` met `limit` op een veld met een bereikindex in indexvolgorde. Al het overige wordt toegepast op een recordscan. `orderBy` op een veld waarvoor de planner geen index kan gebruiken, sorteert de overeenkomende records in PHP. Combineer deze bewerking daarom in grote collecties met geïndexeerde voorwaarden. `count()` gebruikt het aantal indexvermeldingen op `DocStore` en tellers in het geheugen op `SegmentedLog` wanneer het filter één gelijkheidsvoorwaarde bevat.

`cursor($id)` beperkt resultaten tot records na de ID en kan worden gecombineerd met `page()` voor stabiele paginering op record-ID. Zie [Queries](https://storh.inline0.dev/nl/docs/queries) voor gewone streamingfilters zonder de builder.
