diff --git a/src/Aggregating/Metrics/TopHitsAggregation.php b/src/Aggregating/Metrics/TopHitsAggregation.php new file mode 100644 index 0000000..d1c2a7f --- /dev/null +++ b/src/Aggregating/Metrics/TopHitsAggregation.php @@ -0,0 +1,53 @@ +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(); + } + if (!empty($this->source)) { + $body['_source'] = $this->source; + } + + 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 */