Skip to content

Commit 6e061af

Browse files
authored
Merge pull request #7 from ensi-platform/task-96329
#96329 Count aggregation and sort missing values
2 parents ae83afa + 43b48e8 commit 6e061af

File tree

13 files changed

+115
-22
lines changed

13 files changed

+115
-22
lines changed

composer.lock

Lines changed: 12 additions & 9 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/Agregating/AllowedAggregate.php

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,13 +41,18 @@ public static function wrap(self|string $source): self
4141
: self::terms($source);
4242
}
4343

44-
public static function terms(string $name, ?string $field = null): self
44+
public static function terms(string $name, ?string $field = null, ?int $size = null): self
4545
{
46-
return new static($name, new TermsAggregateAction(), $field);
46+
return new static($name, new TermsAggregateAction($size), $field);
4747
}
4848

4949
public static function minmax(string $name, ?string $field = null): self
5050
{
5151
return new static($name, new MinMaxAggregateAction(), $field);
5252
}
53+
54+
public static function count(string $name, ?string $field = null): self
55+
{
56+
return new static($name, new ValueCountAggregateAction(), $field);
57+
}
5358
}

src/Agregating/TermsAggregateAction.php

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,12 @@
77

88
class TermsAggregateAction implements AggregateAction
99
{
10+
public function __construct(private ?int $size = null)
11+
{
12+
}
13+
1014
public function __invoke(AggregationsBuilder $builder, string $name, string $field): void
1115
{
12-
$builder->terms($name, $field);
16+
$builder->terms($name, $field, $this->size);
1317
}
1418
}
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
<?php
2+
3+
namespace Ensi\LaravelElasticQuerySpecification\Agregating;
4+
5+
use Ensi\LaravelElasticQuery\Contracts\AggregationsBuilder;
6+
use Ensi\LaravelElasticQuerySpecification\Contracts\AggregateAction;
7+
8+
class ValueCountAggregateAction implements AggregateAction
9+
{
10+
public function __invoke(AggregationsBuilder $builder, string $name, string $field): void
11+
{
12+
$builder->count($name, $field);
13+
}
14+
}

src/Contracts/SortAction.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,5 +6,5 @@
66

77
interface SortAction
88
{
9-
public function __invoke(SortableQuery $query, string $order, ?string $mode, string $field): void;
9+
public function __invoke(SortableQuery $query, string $order, ?string $mode, string $field, ?string $missingValues): void;
1010
}

src/Sorting/AllowedSort.php

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
namespace Ensi\LaravelElasticQuerySpecification\Sorting;
44

5+
use Ensi\LaravelElasticQuery\Contracts\MissingValuesMode;
56
use Ensi\LaravelElasticQuery\Contracts\SortableQuery;
67
use Ensi\LaravelElasticQuery\Contracts\SortMode;
78
use Ensi\LaravelElasticQuery\Contracts\SortOrder;
@@ -18,6 +19,7 @@ class AllowedSort implements Sort
1819
protected string $field;
1920
protected string $defaultOrder;
2021
protected ?string $mode = null;
22+
protected ?string $missingValues = null;
2123

2224
public function __construct(string $name, SortAction $action, ?string $field = null)
2325
{
@@ -42,7 +44,7 @@ public static function parseNameAndOrder(string $source): array
4244

4345
public function __invoke(SortableQuery $query, ?string $order): void
4446
{
45-
$this->action->__invoke($query, $order ?? $this->defaultOrder, $this->mode, $this->field);
47+
$this->action->__invoke($query, $order ?? $this->defaultOrder, $this->mode, $this->field, $this->missingValues);
4648
}
4749

4850
public function name(): string
@@ -59,6 +61,13 @@ public function mode(string $value): self
5961
return $this;
6062
}
6163

64+
public function missingValuesFirst(): self
65+
{
66+
$this->missingValues = MissingValuesMode::FIRST;
67+
68+
return $this;
69+
}
70+
6271
public function byMin(): self
6372
{
6473
return $this->mode(SortMode::MIN);

src/Sorting/FieldSortAction.php

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

88
class FieldSortAction implements SortAction
99
{
10-
public function __invoke(SortableQuery $query, string $order, ?string $mode, string $field): void
10+
public function __invoke(SortableQuery $query, string $order, ?string $mode, string $field, ?string $missingValues): void
1111
{
12-
$query->sortBy($field, $order, $mode);
12+
$query->sortBy($field, $order, $mode, $missingValues);
1313
}
1414
}

tests/Integration/AggregatingTest.php

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,3 +80,25 @@
8080

8181
expect(fn () => aggQuery($spec, $request))->toThrow(InvalidQueryException::class);
8282
});
83+
84+
test('terms with size', function () {
85+
$spec = CompositeSpecification::new()->allowedAggregates([
86+
AllowedAggregate::terms('tags', size: 2),
87+
]);
88+
89+
$request = ['aggregate' => ['tags']];
90+
91+
aggQuery($spec, $request)
92+
->assertBucketKeysCount('tags', 2);
93+
});
94+
95+
test('count aggregation', function () {
96+
$spec = CompositeSpecification::new()->allowedAggregates([
97+
AllowedAggregate::count('product_count', 'product_id'),
98+
]);
99+
100+
$request = ['aggregate' => ['product_count']];
101+
102+
aggQuery($spec, $request)
103+
->assertValue('product_count', 6);
104+
});

tests/Integration/SortingTest.php

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,3 +55,16 @@
5555
expect(fn () => searchQuery($spec, $request))
5656
->toThrow(InvalidQueryException::class);
5757
});
58+
59+
test('sort missing values', function () {
60+
$spec = CompositeSpecification::new()->allowedSorts([
61+
AllowedSort::field('cashback', 'cashback.value')->missingValuesFirst(),
62+
'product_id',
63+
]);
64+
65+
$request = [
66+
'sort' => ['cashback', 'product_id'],
67+
];
68+
69+
searchQuery($spec, $request)->assertDocumentOrder([405, 471, 319, 1, 150, 328]);
70+
});

tests/Integration/TestAggregationResults.php

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
use Ensi\LaravelElasticQuerySpecification\Specification\CompositeSpecification;
1010
use Ensi\LaravelElasticQuerySpecification\Tests\Data\ProductsIndex;
1111
use Illuminate\Support\Collection;
12+
use function PHPUnit\Framework\assertCount;
1213
use function PHPUnit\Framework\assertEquals;
1314
use function PHPUnit\Framework\assertEqualsCanonicalizing;
1415

@@ -49,13 +50,27 @@ public function assertBucketKeys(string $aggName, array $expected): self
4950
return $this;
5051
}
5152

53+
public function assertBucketKeysCount(string $aggName, int $expected): self
54+
{
55+
assertCount($expected, $this->get($aggName));
56+
57+
return $this;
58+
}
59+
5260
public function assertMinMax(string $aggName, mixed $min, mixed $max): self
5361
{
5462
assertEquals(new MinMax($min, $max), $this->get($aggName));
5563

5664
return $this;
5765
}
5866

67+
public function assertValue(string $aggName, mixed $expected): self
68+
{
69+
assertEquals($expected, $this->get($aggName));
70+
71+
return $this;
72+
}
73+
5974
public function dump(): static
6075
{
6176
$this->results->dump();

0 commit comments

Comments
 (0)