Skip to content

Commit

Permalink
Added Aggregate filter (#9)
Browse files Browse the repository at this point in the history
* Added Aggregate filteer

* Added missing unit test coverage
  • Loading branch information
vladvildanov authored Feb 13, 2024
1 parent b06e415 commit 73713b7
Show file tree
Hide file tree
Showing 11 changed files with 629 additions and 27 deletions.
8 changes: 0 additions & 8 deletions src/Query/Filter/AbstractFilter.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@

namespace Vladvildanov\PredisVl\Query\Filter;

use Vladvildanov\PredisVl\Enum\Condition;

abstract class AbstractFilter implements FilterInterface
{
Expand All @@ -17,13 +16,6 @@ abstract class AbstractFilter implements FilterInterface
'!=' => '-'
];

/**
* @inheritDoc
*/
public function __construct(protected string $fieldName, protected Condition $condition, protected mixed $value)
{
}

/**
* @inheritDoc
*/
Expand Down
95 changes: 95 additions & 0 deletions src/Query/Filter/AggregateFilter.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
<?php

namespace Vladvildanov\PredisVl\Query\Filter;

use Vladvildanov\PredisVl\Enum\Logical;

class AggregateFilter extends AbstractFilter implements AggregateFilterInterface
{
/**
* @var array
*/
private array $filters = [];

/**
* Mapping for logical operators according to query syntax.
*
* @var array
* @link https://redis.io/docs/interact/search-and-query/query/combined/
*/
private array $conjunctionMapping = [
'&&' => ' ',
'||' => ' | ',
];

/**
* Creates an aggregated filter based on the set of given filters.
*
* If the same logical operator should be applied to all filters, you could pass them here in constructor.
* If you need a combination of logical operators use and() or() methods to build suitable aggregate filter.
*
* @param FilterInterface $filters
* @param Logical $conjunction
*/
public function __construct($filters = [], Logical $conjunction = Logical::and)
{
if (!empty($filters)) {
$this->addFilters($filters, $conjunction);
}
}

/**
* @inheritDoc
*/
public function and(FilterInterface ...$filter): AggregateFilterInterface
{
$this->addFilters(func_get_args(), Logical::and);

return $this;
}

/**
* @inheritDoc
*/
public function or(FilterInterface ...$filter): AggregateFilterInterface
{
$this->addFilters(func_get_args(), Logical::or);

return $this;
}

/**
* @inheritDoc
*/
public function toExpression(): string
{
return trim(implode('', $this->filters), ' |');
}

/**
* Add filters with given conjunction into array.
*
* @param FilterInterface[] $filters
* @param Logical $conjunction
* @return void
*/
private function addFilters(array $filters, Logical $conjunction): void
{
if (count($filters) === 1) {
$this->filters[] = $this->conjunctionMapping[$conjunction->value];
$this->filters[] = $filters[0]->toExpression();
} else {
if (!empty($this->filters)) {
$this->filters[] = ' ';
}

foreach ($filters as $i => $filter) {
$this->filters[] = $filter->toExpression();

if ($i !== count($filters) - 1) {
$this->filters[] = $this->conjunctionMapping[$conjunction->value];
}
}
}
}
}
22 changes: 22 additions & 0 deletions src/Query/Filter/AggregateFilterInterface.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
<?php

namespace Vladvildanov\PredisVl\Query\Filter;

interface AggregateFilterInterface extends FilterInterface
{
/**
* Creates an aggregated filter with intersection (AND).
*
* @param FilterInterface ...$filter
* @return AggregateFilterInterface
*/
public function and(FilterInterface...$filter): AggregateFilterInterface;

/**
* Creates an aggregated filter with union (OR).
*
* @param FilterInterface ...$filter
* @return AggregateFilterInterface
*/
public function or(FilterInterface...$filter): AggregateFilterInterface;
}
11 changes: 0 additions & 11 deletions src/Query/Filter/FilterInterface.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,19 +2,8 @@

namespace Vladvildanov\PredisVl\Query\Filter;

use Vladvildanov\PredisVl\Enum\Condition;

interface FilterInterface
{
/**
* Creates field-based filter.
*
* @param string $fieldName
* @param Condition $condition
* @param mixed $value
*/
public function __construct(string $fieldName, Condition $condition, mixed $value);

/**
* Returns expression-string representation of current filter.
*
Expand Down
7 changes: 3 additions & 4 deletions src/Query/Filter/GeoFilter.php
Original file line number Diff line number Diff line change
Expand Up @@ -19,16 +19,15 @@ class GeoFilter extends AbstractFilter
* @param array{lon: float, lat: float, radius: int, unit: Unit} $value
*/
public function __construct(
string $fieldName,
Condition $condition,
protected readonly string $fieldName,
protected readonly Condition $condition,
#[ArrayShape([
'lon' => 'float',
'lat' => 'float',
'radius' => 'int',
'unit' => Unit::class
])] $value
])] protected readonly array $value
) {
parent::__construct($fieldName, $condition, $value);
}

/**
Expand Down
1 change: 0 additions & 1 deletion src/Query/Filter/NumericFilter.php
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@ public function __construct(
protected Condition $condition,
protected mixed $value
) {
parent::__construct($fieldName, $condition, $value);
}

/**
Expand Down
1 change: 0 additions & 1 deletion src/Query/Filter/TagFilter.php
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@ public function __construct(
'tags' => 'array',
])] protected mixed $value
) {
parent::__construct($this->fieldName, $this->condition, $this->value);
}

/**
Expand Down
3 changes: 1 addition & 2 deletions src/Query/Filter/TextFilter.php
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,8 @@ class TextFilter extends AbstractFilter
* @param Condition $condition
* @param string $value
*/
public function __construct(string $fieldName, Condition $condition, $value)
public function __construct(protected string $fieldName, protected Condition $condition, protected string $value)
{
parent::__construct($fieldName, $condition, $value);
}

/**
Expand Down
Loading

0 comments on commit 73713b7

Please sign in to comment.