Skip to content

Commit

Permalink
Add withMaxDepth() helper
Browse files Browse the repository at this point in the history
  • Loading branch information
staudenmeir committed Jun 5, 2022
1 parent d2fcb14 commit 1e5d167
Show file tree
Hide file tree
Showing 3 changed files with 59 additions and 0 deletions.
24 changes: 24 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -755,6 +755,12 @@ $constraint = function ($query) {
$subgraph = Node::subgraph($constraint)->get();
```

You can pass a maximum depth as the second argument

```php
$subgraph = Node::subgraph($constraint, 5)->get();
```

#### <a name="graphs-order">Order</a>

The trait provides query scopes to order nodes breadth-first or depth-first:
Expand Down Expand Up @@ -805,6 +811,24 @@ $descendants = Node::find($id)->descendants()->whereDepth(2)->get();
$descendants = Node::find($id)->descendants()->whereDepth('<', 3)->get();
```

Queries with `whereDepth()` constraints that limit the maximum depth still build the entire (sub)graph internally.
Use `withMaxDepth()` to set a maximum depth that improves query performance by only building the requested section of
the graph:

```php
$descendants = Node::withMaxDepth(5, function () {
return Node::find($id)->descendants;
});
```

This also works with negative depths (where it's technically a minimum):

```php
$ancestors = Node::withMaxDepth(-5, function () {
return Node::find($id)->ancestors;
});
```

#### <a name="graphs-path">Path</a>

The results of ancestor, descendant and subgraph queries include an additional `path` column.
Expand Down
17 changes: 17 additions & 0 deletions src/Eloquent/Traits/HasGraphAdjacencyList.php
Original file line number Diff line number Diff line change
Expand Up @@ -458,4 +458,21 @@ public static function withRecursiveQueryConstraint(callable $constraint, callab

return $result;
}

/**
* Execute a query with a maximum depth constraint for the recursive query.
*
* @param int $maxDepth
* @param callable $query
* @return mixed
*/
public static function withMaxDepth(int $maxDepth, callable $query): mixed
{
$operator = $maxDepth > 0 ? '<' : '>';

return static::withRecursiveQueryConstraint(
fn (Builder $query) => $query->whereDepth($operator, $maxDepth),
$query
);
}
}
18 changes: 18 additions & 0 deletions tests/Graph/EloquentTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -117,4 +117,22 @@ public function testWithRecursiveQueryConstraint()

$this->assertEquals([54, 74, 84, 84], $nodes->pluck('id')->all());
}

public function testWithMaxDepth()
{
$nodes = Node::withMaxDepth(2, function () {
return Node::find(24)->descendants;
});

$this->assertEquals([54, 74, 84], $nodes->pluck('id')->all());
}

public function testWithMaxDepthWithNegativeDepth()
{
$nodes = Node::withMaxDepth(-1, function () {
return Node::find(54)->ancestors;
});

$this->assertEquals([14, 24, 104], $nodes->pluck('id')->all());
}
}

0 comments on commit 1e5d167

Please sign in to comment.