Skip to content

Commit 3297d5a

Browse files
committed
#102033 terms composite aggs
1 parent a0d1b3e commit 3297d5a

File tree

5 files changed

+84
-10
lines changed

5 files changed

+84
-10
lines changed

src/Aggregating/Bucket.php

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,12 @@
44

55
class Bucket
66
{
7-
public function __construct(public mixed $key, public int $count)
7+
public function __construct(public mixed $key, public int $count, protected array $compositeValues = [])
88
{
99
}
10+
11+
public function getCompositeValue(string $name): mixed
12+
{
13+
return $this->compositeValues[$name] ?? null;
14+
}
1015
}

src/Aggregating/Bucket/TermsAggregation.php

Lines changed: 29 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,18 @@
55
use Ensi\LaravelElasticQuery\Aggregating\BucketCollection;
66
use Ensi\LaravelElasticQuery\Aggregating\Result;
77
use Ensi\LaravelElasticQuery\Contracts\Aggregation;
8+
use Ensi\LaravelElasticQuery\Search\Sorting\Sort;
89
use Webmozart\Assert\Assert;
910

1011
class TermsAggregation implements Aggregation
1112
{
12-
public function __construct(private string $name, private string $field, private ?int $size = null)
13-
{
13+
public function __construct(
14+
private string $name,
15+
private string $field,
16+
private ?int $size = null,
17+
private ?Sort $sort = null,
18+
private ?Aggregation $composite = null,
19+
) {
1420
Assert::stringNotEmpty(trim($name));
1521
Assert::stringNotEmpty(trim($field));
1622
Assert::nullOrGreaterThan($this->size, 0);
@@ -29,20 +35,39 @@ public function toDSL(): array
2935
$body['size'] = $this->size;
3036
}
3137

32-
return [
38+
if ($this->sort) {
39+
$body['order'] = $this->sort->toDSL();
40+
}
41+
42+
$dsl = [
3343
$this->name => [
3444
'terms' => $body,
3545
],
3646
];
47+
48+
if ($this->isComposite()) {
49+
$dsl[$this->name]['aggs'] = $this->composite->toDSL();
50+
}
51+
52+
return $dsl;
3753
}
3854

3955
public function parseResults(array $response): array
4056
{
4157
$buckets = array_map(
42-
fn (array $bucket) => Result::parseBucket($bucket),
58+
function (array $bucket) {
59+
$values = $this->isComposite() ? $this->composite->parseResults($bucket) : [];
60+
61+
return Result::parseBucket($bucket, $values);
62+
},
4363
$response[$this->name]['buckets'] ?? []
4464
);
4565

4666
return [$this->name => new BucketCollection($buckets)];
4767
}
68+
69+
public function isComposite(): bool
70+
{
71+
return isset($this->composite);
72+
}
4873
}
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
<?php
2+
3+
namespace Ensi\LaravelElasticQuery\Aggregating\Metrics;
4+
5+
use Ensi\LaravelElasticQuery\Aggregating\MinMax;
6+
use Ensi\LaravelElasticQuery\Aggregating\Result;
7+
use Ensi\LaravelElasticQuery\Contracts\Aggregation;
8+
use Webmozart\Assert\Assert;
9+
10+
class MinMaxScoreAggregation implements Aggregation
11+
{
12+
public function __construct(protected string $name = 'score')
13+
{
14+
Assert::stringNotEmpty(trim($name));
15+
}
16+
17+
public function name(): string
18+
{
19+
return $this->name;
20+
}
21+
22+
public function toDSL(): array
23+
{
24+
return [
25+
"{$this->name}_min" => ['min' => ['script' => "_score"]],
26+
"{$this->name}_max" => ['max' => ['script' => "_score"]],
27+
];
28+
}
29+
30+
public function parseResults(array $response): array
31+
{
32+
return [$this->name => new MinMax(
33+
Result::parseValue($response["{$this->name}_min"]) ?? 0,
34+
Result::parseValue($response["{$this->name}_max"]) ?? 0,
35+
)];
36+
}
37+
}

src/Aggregating/Result.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,9 @@ public static function parseValue(array $source): mixed
99
return self::parse($source, 'value');
1010
}
1111

12-
public static function parseBucket(array $source): Bucket
12+
public static function parseBucket(array $source, array $compositeValues = []): Bucket
1313
{
14-
return new Bucket(self::parse($source, 'key'), (int)($source['doc_count'] ?? 0));
14+
return new Bucket(self::parse($source, 'key'), (int)($source['doc_count'] ?? 0), $compositeValues);
1515
}
1616

1717
public static function parse(array $source, string $key): mixed

src/Concerns/ConstructsAggregations.php

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,9 @@
99
use Ensi\LaravelElasticQuery\Aggregating\CompositeAggregationBuilder;
1010
use Ensi\LaravelElasticQuery\Aggregating\Metrics\MinMaxAggregation;
1111
use Ensi\LaravelElasticQuery\Aggregating\Metrics\ValueCountAggregation;
12+
use Ensi\LaravelElasticQuery\Contracts\Aggregation;
1213
use Ensi\LaravelElasticQuery\Filtering\BoolQueryBuilder;
14+
use Ensi\LaravelElasticQuery\Search\Sorting\Sort;
1315

1416
trait ConstructsAggregations
1517
{
@@ -19,9 +21,14 @@ trait ConstructsAggregations
1921
protected AggregationCollection $aggregations;
2022
protected BoolQueryBuilder $boolQuery;
2123

22-
public function terms(string $name, string $field, ?int $size = null): static
23-
{
24-
$this->aggregations->add(new TermsAggregation($name, $this->absolutePath($field), $size));
24+
public function terms(
25+
string $name,
26+
string $field,
27+
?int $size = null,
28+
?Sort $sort = null,
29+
?Aggregation $composite = null,
30+
): static {
31+
$this->aggregations->add(new TermsAggregation($name, $this->absolutePath($field), $size, $sort, $composite));
2532

2633
return $this;
2734
}

0 commit comments

Comments
 (0)