
# Query Builder

`DocStore` dan `SegmentedLog` menyediakan `query()`. `DocStore` dapat menggunakan indeks sekunder; `SegmentedLog` menerapkan predikat yang sama pada catatan yang dialirkan.

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

Metode terminal yang berguna:

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

Pada `DocStore`, dua kondisi `eq` pada kolom berindeks kesetaraan non-unik dapat menggunakan bucket gabungan otomatis. Kesetaraan tunggal, `in`, dan operator rentang tetap menggunakan indeks kolom yang dikonfigurasi.

Operator:

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

`andWhere` dan `orWhere` menggunakan callback karena `and` dan `or` adalah kata kunci PHP yang dicadangkan:

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

Pemanggilan `where()` berantai digabungkan dengan AND; setiap cabang `orWhere()` menambahkan alternatif.

## Cara kerja eksekusi

Setiap kondisi berfungsi pada setiap koleksi; indeks hanya mengubah biayanya. Pada `DocStore`, `eq` dan `in` menggunakan indeks kesetaraan, operator rentang dan `prefix` menggunakan indeks rentang, dan `orderBy` dengan `limit` pada kolom berindeks rentang membaca sesuai urutan indeks. Selebihnya memfilter pemindaian catatan. `orderBy` pada kolom yang tidak dapat dilayani planner dengan indeks akan mengurutkan catatan yang cocok di PHP, jadi untuk koleksi besar, padukan dengan kondisi berindeks. `count()` menggunakan jumlah entri indeks pada `DocStore` dan penghitung dalam memori pada `SegmentedLog` jika filternya berupa satu kesetaraan.

`cursor($id)` membatasi hasil ke catatan setelah ID tersebut, dan dapat digabungkan dengan `page()` untuk paginasi stabil yang diurutkan berdasarkan ID catatan. Untuk filter streaming biasa tanpa builder, lihat [Kueri](https://storh.inline0.dev/id/docs/queries).
