Skip to content

Commit

Permalink
Add Bucket sort aggregation
Browse files Browse the repository at this point in the history
  • Loading branch information
Gaëtan Petit committed Oct 14, 2024
1 parent e2cb89b commit af2edd4
Show file tree
Hide file tree
Showing 2 changed files with 137 additions and 0 deletions.
52 changes: 52 additions & 0 deletions src/Aggregation/BucketSort.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
<?php

declare(strict_types=1);

namespace Elastica\Aggregation;

use Elastica\Exception\InvalidException;

class BucketSort extends AbstractAggregation implements GapPolicyInterface
{
use Traits\GapPolicyTrait;

public function toArray(): array
{
if (!$this->hasParam('sort') && !$this->hasParam('size') && !$this->hasParam('from')) {
throw new InvalidException('Either the sort param, the size param or the from param should be set');
}

return parent::toArray();
}

/**
* The number of buckets to return. Defaults to all buckets of the parent aggregation.
*
* @return $this
*/
public function setSize(int $size): self
{
return $this->setParam('size', $size);
}

/**
* Buckets in positions prior to the set value will be truncated.
*
* @return $this
*/
public function setFrom(int $from): self
{
return $this->setParam('from', $from);
}

/**
* How the top matching hits should be sorted. By default the hits are sorted by the score of the main query.
*
* @param string $aggregationName the name of an aggregation
* @param string $direction "asc" or "desc"
*/
public function addSort(string $aggregationName, string $direction): self
{
return $this->addParam('sort', [$aggregationName => ['order' => $direction]]);
}
}
85 changes: 85 additions & 0 deletions tests/Aggregation/BucketSortTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
<?php

declare(strict_types=1);

namespace Elastica\Test\Aggregation;

use Elastica\Aggregation\BucketSort;
use Elastica\Aggregation\Sum;
use Elastica\Aggregation\Terms;
use Elastica\Document;
use Elastica\Index;
use Elastica\Mapping;
use Elastica\Query;

/**
* @internal
*/
class BucketSortTest extends BaseAggregationTest
{
/**
* @group functional
*/
public function testBucketSortAggregation(): void
{
$bucketSortAggregation = new BucketSort('sort_by_bucket');
$bucketSortAggregation->addSort('sum_metric_a', 'desc');
$agg = $this->getAggregation();
$agg->addAggregation($bucketSortAggregation);

$query = new Query();
$query->addAggregation($agg);
$results = $this->_getIndexForTest()->search($query)->getAggregations();

$this->assertSame('bar', $results['terms']['buckets'][0]['key']);

$bucketSortAggregation = new BucketSort('sort_by_bucket');
$bucketSortAggregation->addSort('sum_metric_a', 'asc');
$agg = $this->getAggregation();
$agg->addAggregation($bucketSortAggregation);

$query = new Query();
$query->addAggregation($agg);
$results = $this->_getIndexForTest()->search($query)->getAggregations();

$this->assertSame('foo', $results['terms']['buckets'][0]['key']);
}

protected function _getIndexForTest(): Index
{
$index = $this->_createIndex();
$index->setMapping(new Mapping([
'field_a' => ['type' => 'keyword'],
'metric_a' => ['type' => 'integer'],
]));

$index->addDocuments([
new Document('1', ['field_a' => 'foo', 'metric_a' => 1]),
new Document('2', ['field_a' => 'foo', 'metric_a' => 1]),
new Document('3', ['field_a' => 'foo', 'metric_a' => 1]),
new Document('4', ['field_a' => 'bar', 'metric_a' => 10]),
new Document('5', ['field_a' => 'bar', 'metric_a' => 10]),
new Document('6', ['field_a' => 'bar', 'metric_a' => 10]),
]);

$index->refresh();

return $index;
}

private function getAggregation(): Terms
{
$agg = new Terms('terms');
$agg->setField('field_a');

$subAgg = new Sum('sum_metric_a');
$subAgg->setField('metric_a');
$agg->addAggregation($subAgg);

$subAgg = new Sum('sum_metric_b');
$subAgg->setField('metric_b');
$agg->addAggregation($subAgg);

return $agg;
}
}

0 comments on commit af2edd4

Please sign in to comment.