From 738048e319f7d50df14242513d23cac3fef0c6cc Mon Sep 17 00:00:00 2001 From: Evgenij Manoylin Date: Thu, 20 Feb 2025 17:32:07 +0300 Subject: [PATCH 1/2] IDBPR-2901 Add TopHits v8 --- .../Metrics/TopHitsAggregation.php | 49 +++++++++++++++++++ .../AggregationQueryIntegrationTest.php | 30 ++++++++++++ 2 files changed, 79 insertions(+) create mode 100644 src/Aggregating/Metrics/TopHitsAggregation.php diff --git a/src/Aggregating/Metrics/TopHitsAggregation.php b/src/Aggregating/Metrics/TopHitsAggregation.php new file mode 100644 index 0000000..dc4162d --- /dev/null +++ b/src/Aggregating/Metrics/TopHitsAggregation.php @@ -0,0 +1,49 @@ +size, 0); + } + + public function name(): string + { + return $this->name; + } + + public function parseResults(array $response): array + { + return [$this->name => $response[$this->name]['hits']['hits'] ?? []]; + } + + public function toDSL(): array + { + $body = []; + + if ($this->size !== null) { + $body['size'] = $this->size; + } + + if ($this->sort) { + $body['sort'] = $this->sort->toDSL(); + } + + return [ + $this->name => [ + 'top_hits' => empty($body) ? new stdClass() : $body, + ], + ]; + } +} diff --git a/tests/IntegrationTests/AggregationQueryIntegrationTest.php b/tests/IntegrationTests/AggregationQueryIntegrationTest.php index 42f0489..0fc29db 100644 --- a/tests/IntegrationTests/AggregationQueryIntegrationTest.php +++ b/tests/IntegrationTests/AggregationQueryIntegrationTest.php @@ -2,6 +2,7 @@ use Ensi\LaravelElasticQuery\Aggregating\Bucket; use Ensi\LaravelElasticQuery\Aggregating\Metrics\MinMaxScoreAggregation; +use Ensi\LaravelElasticQuery\Aggregating\Metrics\TopHitsAggregation; use Ensi\LaravelElasticQuery\Aggregating\MinMax; use Ensi\LaravelElasticQuery\Contracts\AggregationsBuilder; use Ensi\LaravelElasticQuery\Search\Sorting\Sort; @@ -53,6 +54,35 @@ ); }); +test('aggregation query top hits', function () { + /** @var IntegrationTestCase $this */ + + $results = ProductsIndex::aggregate() + ->terms( + name: 'group_by', + field: 'active', + composite: new TopHitsAggregation( + 'top_products', + size: 10 + ) + ) + ->get(); + + $results = $results->get('group_by'); + + /** @var Bucket $result */ + foreach ($results as $result) { + $groupByKey = $result->key; + /** @var array $products */ + $products = $result->getCompositeValue('top_products'); + + array_walk($products, fn ($hit) => assertEquals($groupByKey, data_get($hit, '_source.active'))); + $productIds = array_map(fn ($hit) => data_get($hit, '_source.product_id'), $products); + + assertEqualsCanonicalizing($groupByKey ? [1, 150, 328, 405, 471] : [319], $productIds); + } +}); + test('aggregation query cardinality', function () { /** @var IntegrationTestCase $this */ From 55457b77beb416b2a48bf549b1890d1a9f8de295 Mon Sep 17 00:00:00 2001 From: Evgenij Manoylin Date: Fri, 21 Feb 2025 10:34:11 +0300 Subject: [PATCH 2/2] =?UTF-8?q?=D0=94=D0=BE=D0=B1=D0=B0=D0=B2=D0=BB=D0=B5?= =?UTF-8?q?=D0=BD=D0=B0=20=D0=B2=D0=BE=D0=B7=D0=BC=D0=BE=D0=B6=D0=BD=D0=BE?= =?UTF-8?q?=D1=81=D1=82=D1=8C=20=D0=B2=D1=8B=D0=B1=D0=BE=D1=80=D0=B0=20?= =?UTF-8?q?=D0=BD=D1=83=D0=B6=D0=BD=D1=8B=D1=85=20=D0=BF=D0=BE=D0=BB=D0=B5?= =?UTF-8?q?=D0=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Aggregating/Metrics/TopHitsAggregation.php | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/Aggregating/Metrics/TopHitsAggregation.php b/src/Aggregating/Metrics/TopHitsAggregation.php index dc4162d..d1c2a7f 100644 --- a/src/Aggregating/Metrics/TopHitsAggregation.php +++ b/src/Aggregating/Metrics/TopHitsAggregation.php @@ -12,7 +12,8 @@ class TopHitsAggregation implements Aggregation public function __construct( private string $name, private ?int $size = null, - protected ?SortCollection $sort = null, + private array $source = [], + private ?SortCollection $sort = null, ) { Assert::stringNotEmpty(trim($name)); Assert::nullOrGreaterThan($this->size, 0); @@ -39,6 +40,9 @@ public function toDSL(): array if ($this->sort) { $body['sort'] = $this->sort->toDSL(); } + if (!empty($this->source)) { + $body['_source'] = $this->source; + } return [ $this->name => [