Skip to content

Commit 73713b7

Browse files
authored
Added Aggregate filter (#9)
* Added Aggregate filteer * Added missing unit test coverage
1 parent b06e415 commit 73713b7

File tree

11 files changed

+629
-27
lines changed

11 files changed

+629
-27
lines changed

src/Query/Filter/AbstractFilter.php

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22

33
namespace Vladvildanov\PredisVl\Query\Filter;
44

5-
use Vladvildanov\PredisVl\Enum\Condition;
65

76
abstract class AbstractFilter implements FilterInterface
87
{
@@ -17,13 +16,6 @@ abstract class AbstractFilter implements FilterInterface
1716
'!=' => '-'
1817
];
1918

20-
/**
21-
* @inheritDoc
22-
*/
23-
public function __construct(protected string $fieldName, protected Condition $condition, protected mixed $value)
24-
{
25-
}
26-
2719
/**
2820
* @inheritDoc
2921
*/

src/Query/Filter/AggregateFilter.php

Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
<?php
2+
3+
namespace Vladvildanov\PredisVl\Query\Filter;
4+
5+
use Vladvildanov\PredisVl\Enum\Logical;
6+
7+
class AggregateFilter extends AbstractFilter implements AggregateFilterInterface
8+
{
9+
/**
10+
* @var array
11+
*/
12+
private array $filters = [];
13+
14+
/**
15+
* Mapping for logical operators according to query syntax.
16+
*
17+
* @var array
18+
* @link https://redis.io/docs/interact/search-and-query/query/combined/
19+
*/
20+
private array $conjunctionMapping = [
21+
'&&' => ' ',
22+
'||' => ' | ',
23+
];
24+
25+
/**
26+
* Creates an aggregated filter based on the set of given filters.
27+
*
28+
* If the same logical operator should be applied to all filters, you could pass them here in constructor.
29+
* If you need a combination of logical operators use and() or() methods to build suitable aggregate filter.
30+
*
31+
* @param FilterInterface $filters
32+
* @param Logical $conjunction
33+
*/
34+
public function __construct($filters = [], Logical $conjunction = Logical::and)
35+
{
36+
if (!empty($filters)) {
37+
$this->addFilters($filters, $conjunction);
38+
}
39+
}
40+
41+
/**
42+
* @inheritDoc
43+
*/
44+
public function and(FilterInterface ...$filter): AggregateFilterInterface
45+
{
46+
$this->addFilters(func_get_args(), Logical::and);
47+
48+
return $this;
49+
}
50+
51+
/**
52+
* @inheritDoc
53+
*/
54+
public function or(FilterInterface ...$filter): AggregateFilterInterface
55+
{
56+
$this->addFilters(func_get_args(), Logical::or);
57+
58+
return $this;
59+
}
60+
61+
/**
62+
* @inheritDoc
63+
*/
64+
public function toExpression(): string
65+
{
66+
return trim(implode('', $this->filters), ' |');
67+
}
68+
69+
/**
70+
* Add filters with given conjunction into array.
71+
*
72+
* @param FilterInterface[] $filters
73+
* @param Logical $conjunction
74+
* @return void
75+
*/
76+
private function addFilters(array $filters, Logical $conjunction): void
77+
{
78+
if (count($filters) === 1) {
79+
$this->filters[] = $this->conjunctionMapping[$conjunction->value];
80+
$this->filters[] = $filters[0]->toExpression();
81+
} else {
82+
if (!empty($this->filters)) {
83+
$this->filters[] = ' ';
84+
}
85+
86+
foreach ($filters as $i => $filter) {
87+
$this->filters[] = $filter->toExpression();
88+
89+
if ($i !== count($filters) - 1) {
90+
$this->filters[] = $this->conjunctionMapping[$conjunction->value];
91+
}
92+
}
93+
}
94+
}
95+
}
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
<?php
2+
3+
namespace Vladvildanov\PredisVl\Query\Filter;
4+
5+
interface AggregateFilterInterface extends FilterInterface
6+
{
7+
/**
8+
* Creates an aggregated filter with intersection (AND).
9+
*
10+
* @param FilterInterface ...$filter
11+
* @return AggregateFilterInterface
12+
*/
13+
public function and(FilterInterface...$filter): AggregateFilterInterface;
14+
15+
/**
16+
* Creates an aggregated filter with union (OR).
17+
*
18+
* @param FilterInterface ...$filter
19+
* @return AggregateFilterInterface
20+
*/
21+
public function or(FilterInterface...$filter): AggregateFilterInterface;
22+
}

src/Query/Filter/FilterInterface.php

Lines changed: 0 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -2,19 +2,8 @@
22

33
namespace Vladvildanov\PredisVl\Query\Filter;
44

5-
use Vladvildanov\PredisVl\Enum\Condition;
6-
75
interface FilterInterface
86
{
9-
/**
10-
* Creates field-based filter.
11-
*
12-
* @param string $fieldName
13-
* @param Condition $condition
14-
* @param mixed $value
15-
*/
16-
public function __construct(string $fieldName, Condition $condition, mixed $value);
17-
187
/**
198
* Returns expression-string representation of current filter.
209
*

src/Query/Filter/GeoFilter.php

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -19,16 +19,15 @@ class GeoFilter extends AbstractFilter
1919
* @param array{lon: float, lat: float, radius: int, unit: Unit} $value
2020
*/
2121
public function __construct(
22-
string $fieldName,
23-
Condition $condition,
22+
protected readonly string $fieldName,
23+
protected readonly Condition $condition,
2424
#[ArrayShape([
2525
'lon' => 'float',
2626
'lat' => 'float',
2727
'radius' => 'int',
2828
'unit' => Unit::class
29-
])] $value
29+
])] protected readonly array $value
3030
) {
31-
parent::__construct($fieldName, $condition, $value);
3231
}
3332

3433
/**

src/Query/Filter/NumericFilter.php

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,6 @@ public function __construct(
1616
protected Condition $condition,
1717
protected mixed $value
1818
) {
19-
parent::__construct($fieldName, $condition, $value);
2019
}
2120

2221
/**

src/Query/Filter/TagFilter.php

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,6 @@ public function __construct(
2424
'tags' => 'array',
2525
])] protected mixed $value
2626
) {
27-
parent::__construct($this->fieldName, $this->condition, $this->value);
2827
}
2928

3029
/**

src/Query/Filter/TextFilter.php

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,9 +21,8 @@ class TextFilter extends AbstractFilter
2121
* @param Condition $condition
2222
* @param string $value
2323
*/
24-
public function __construct(string $fieldName, Condition $condition, $value)
24+
public function __construct(protected string $fieldName, protected Condition $condition, protected string $value)
2525
{
26-
parent::__construct($fieldName, $condition, $value);
2726
}
2827

2928
/**

0 commit comments

Comments
 (0)