Skip to content

Commit 738048e

Browse files
committed
IDBPR-2901 Add TopHits v8
1 parent 91ad988 commit 738048e

File tree

2 files changed

+79
-0
lines changed

2 files changed

+79
-0
lines changed
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
<?php
2+
3+
namespace Ensi\LaravelElasticQuery\Aggregating\Metrics;
4+
5+
use Ensi\LaravelElasticQuery\Contracts\Aggregation;
6+
use Ensi\LaravelElasticQuery\Search\Sorting\SortCollection;
7+
use stdClass;
8+
use Webmozart\Assert\Assert;
9+
10+
class TopHitsAggregation implements Aggregation
11+
{
12+
public function __construct(
13+
private string $name,
14+
private ?int $size = null,
15+
protected ?SortCollection $sort = null,
16+
) {
17+
Assert::stringNotEmpty(trim($name));
18+
Assert::nullOrGreaterThan($this->size, 0);
19+
}
20+
21+
public function name(): string
22+
{
23+
return $this->name;
24+
}
25+
26+
public function parseResults(array $response): array
27+
{
28+
return [$this->name => $response[$this->name]['hits']['hits'] ?? []];
29+
}
30+
31+
public function toDSL(): array
32+
{
33+
$body = [];
34+
35+
if ($this->size !== null) {
36+
$body['size'] = $this->size;
37+
}
38+
39+
if ($this->sort) {
40+
$body['sort'] = $this->sort->toDSL();
41+
}
42+
43+
return [
44+
$this->name => [
45+
'top_hits' => empty($body) ? new stdClass() : $body,
46+
],
47+
];
48+
}
49+
}

tests/IntegrationTests/AggregationQueryIntegrationTest.php

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

33
use Ensi\LaravelElasticQuery\Aggregating\Bucket;
44
use Ensi\LaravelElasticQuery\Aggregating\Metrics\MinMaxScoreAggregation;
5+
use Ensi\LaravelElasticQuery\Aggregating\Metrics\TopHitsAggregation;
56
use Ensi\LaravelElasticQuery\Aggregating\MinMax;
67
use Ensi\LaravelElasticQuery\Contracts\AggregationsBuilder;
78
use Ensi\LaravelElasticQuery\Search\Sorting\Sort;
@@ -53,6 +54,35 @@
5354
);
5455
});
5556

57+
test('aggregation query top hits', function () {
58+
/** @var IntegrationTestCase $this */
59+
60+
$results = ProductsIndex::aggregate()
61+
->terms(
62+
name: 'group_by',
63+
field: 'active',
64+
composite: new TopHitsAggregation(
65+
'top_products',
66+
size: 10
67+
)
68+
)
69+
->get();
70+
71+
$results = $results->get('group_by');
72+
73+
/** @var Bucket $result */
74+
foreach ($results as $result) {
75+
$groupByKey = $result->key;
76+
/** @var array $products */
77+
$products = $result->getCompositeValue('top_products');
78+
79+
array_walk($products, fn ($hit) => assertEquals($groupByKey, data_get($hit, '_source.active')));
80+
$productIds = array_map(fn ($hit) => data_get($hit, '_source.product_id'), $products);
81+
82+
assertEqualsCanonicalizing($groupByKey ? [1, 150, 328, 405, 471] : [319], $productIds);
83+
}
84+
});
85+
5686
test('aggregation query cardinality', function () {
5787
/** @var IntegrationTestCase $this */
5888

0 commit comments

Comments
 (0)