Files
lucent-laravel/docs/Queries.md
T
2026-04-20 21:13:31 +03:00

174 lines
4.5 KiB
Markdown

---
gitea: none
include_toc: true
---
# Queries
The `Query` class is the main way to fetch records. Inject it via the Laravel container.
```php
public function __construct(private Query $query) {}
```
## Return Formats
Queries return results in two formats:
**Graph** — via `->run()`. Returns a `Graph` object with `records` and `edges` collections. Useful for network-style data.
**Tree** — via `->tree()`. Returns a flat `Collection` of records where each record has `_children` and `_parents` arrays populated based on the requested depth. This is the most common format.
## Chaining Methods
All methods return `$this` and can be chained:
| Method | Description |
|---|---|
| `->filter(array)` | Add an AND filter |
| `->orFilter(array)` | Add an OR filter (grouped) |
| `->limit(int)` | Max number of root records to return |
| `->skip(int)` | Offset for pagination |
| `->sort(string)` | Sort by field. Prefix with `-` for descending e.g. `"-_sys.updatedAt"` |
| `->status(array)` | Filter by status array e.g. `["published", "draft"]` |
| `->onlyPublished()` | Shorthand for `->status(["published"])` |
| `->childrenDepth(int)` | How many levels of children to load |
| `->childrenLimit(int)` | Max children per record |
| `->childrenFields(array)` | Only follow specific relationship fields |
| `->parentsDepth(int)` | How many levels of parents to load |
| `->parentsLimit(int)` | Max parents per record |
| `->parentFields(array)` | Only follow specific relationship fields |
| `->notLinked(string)` | Return only records with no parents |
| `->run()` | Execute and return a `Graph` |
| `->tree()` | Execute and return a `Collection` (tree format) |
| `->runWithCount()` | Execute and return a `Graph` with a `total` count |
## Filters
Filter keys use the format `field_operator`. When no operator suffix is given, `eq` is assumed.
```php
$query->filter(["field_operator" => "value"]);
// No operator = eq
$query->filter(["schema" => "blogPosts"]);
// With operator
$query->filter(["_sys.updatedAt_gte" => "2024-01-01"]);
```
### Operator Reference
| Operator | Description |
|---|---|
| _(none)_ or `eq` | Equals (string) |
| `ne` | Not equals (string) |
| `eqnum` | Equals (numeric) |
| `neqnum` | Not equals (numeric) |
| `eqtrue` | Equals `true` |
| `eqfalse` | Equals `false` |
| `netrue` | Not equals `true` |
| `nefalse` | Not equals `false` |
| `regex` | Regular expression match |
| `in` | Value is in array (strings) |
| `nin` | Value is not in array (strings) |
| `innum` | Value is in array (numeric) |
| `ninnum` | Value is not in array (numeric) |
| `lt` | Less than |
| `lte` | Less than or equal |
| `gt` | Greater than |
| `gte` | Greater than or equal |
| `null` | Field is null |
| `nnull` | Field is not null |
| `exists` | Field key exists |
| `nexists` | Field key does not exist |
| `filter` | Raw filter passthrough |
### OR Filters
```php
$query
->filter(["schema" => "blogPosts"])
->orFilter(["title_regex" => "search", "slug_regex" => "search"]);
```
Each `orFilter` call groups its arguments with OR between them. Multiple `orFilter` / `filter` calls are AND-ed together.
### Cross-Schema (Children) Filters
You can filter records by properties of their related records using the `children.` prefix:
```php
$query->filter([
"schema" => "blogPosts",
"children.categories.data.slug" => "sports",
]);
```
This returns `blogPosts` that have a child in `categories` where `slug` equals `sports`.
## Nested Data Fields
Use dot notation to filter on JSON data fields and system fields:
```php
// Filter on a data field
$query->filter(["data.status_eq" => "draft"]);
// Filter on a system field
$query->filter(["_sys.updatedAt_gte" => "2024-01-01"]);
```
## Examples
**Get published blog posts, newest first:**
```php
$posts = $query
->filter(["schema" => "blogPosts"])
->onlyPublished()
->sort("-_sys.updatedAt")
->limit(10)
->tree();
```
**Get posts from a specific category with children loaded:**
```php
$posts = $query
->filter([
"schema" => "blogPosts",
"children.categories.data.slug" => "sports",
])
->childrenDepth(1)
->childrenFields(["categories"])
->limit(10)
->tree();
```
**Paginate records:**
```php
$graph = $query
->filter(["schema" => "blogPosts"])
->limit(20)
->skip(40)
->runWithCount();
$posts = $graph->tree();
$total = $graph->total;
```
**Search across fields:**
```php
$results = $query
->filter(["schema" => "blogPosts"])
->orFilter(["title_regex" => $term, "slug_regex" => $term])
->limit(10)
->tree();
```