Skip to content

Commit

Permalink
Add the Normalize aggregation (#1956)
Browse files Browse the repository at this point in the history
  • Loading branch information
panychek authored Apr 26, 2021
1 parent f8a88d5 commit dd88070
Show file tree
Hide file tree
Showing 6 changed files with 216 additions and 0 deletions.
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
## [Unreleased](https://github.com/ruflin/Elastica/compare/7.1.1...master)
### Backward Compatibility Breaks
### Added

* Added `Elastica\Aggregation\NormalizeAggregation` [#1956](https://github.com/ruflin/Elastica/pull/1956)

### Changed
* Updated `php-cs-fixer` to `2.18.6` [#1955](https://github.com/ruflin/Elastica/pull/1955)
* Using default Elasticsearch images for testing instead of OSS https://github.com/ruflin/Elastica/pull/1954
Expand Down
72 changes: 72 additions & 0 deletions src/Aggregation/NormalizeAggregation.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
<?php

namespace Elastica\Aggregation;

use Elastica\Exception\InvalidException;

/**
* Class NormalizeAggregation.
*
* @see https://www.elastic.co/guide/en/elasticsearch/reference/current/search-aggregations-pipeline-normalize-aggregation.html
*/
class NormalizeAggregation extends AbstractAggregation
{
public function __construct(string $name, ?string $bucketsPath = null, ?string $method = null)
{
parent::__construct($name);

if (null !== $bucketsPath) {
$this->setBucketsPath($bucketsPath);
}

if (null !== $method) {
$this->setMethod($method);
}
}

/**
* Set the buckets_path for this aggregation.
*
* @return $this
*/
public function setBucketsPath(string $bucketsPath): self
{
return $this->setParam('buckets_path', $bucketsPath);
}

/**
* Set the method for this aggregation.
*
* @return $this
*/
public function setMethod(string $method): self
{
return $this->setParam('method', $method);
}

/**
* Set the format for this aggregation.
*
* @return $this
*/
public function setFormat(string $format): self
{
return $this->setParam('format', $format);
}

/**
* @throws InvalidException If buckets path or method are not set
*/
public function toArray(): array
{
if (!$this->hasParam('buckets_path')) {
throw new InvalidException('Buckets path is required');
}

if (!$this->hasParam('method')) {
throw new InvalidException('Method parameter is required');
}

return parent::toArray();
}
}
11 changes: 11 additions & 0 deletions src/QueryBuilder/DSL/Aggregation.php
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
use Elastica\Aggregation\Min;
use Elastica\Aggregation\Missing;
use Elastica\Aggregation\Nested;
use Elastica\Aggregation\NormalizeAggregation;
use Elastica\Aggregation\Percentiles;
use Elastica\Aggregation\PercentilesBucket;
use Elastica\Aggregation\Range;
Expand Down Expand Up @@ -487,4 +488,14 @@ public function composite(string $name): Composite
{
return new Composite($name);
}

/**
* normalize aggregation.
*
* @see https://www.elastic.co/guide/en/elasticsearch/reference/current/search-aggregations-pipeline-normalize-aggregation.html
*/
public function normalize(string $name, ?string $bucketsPath = null, ?string $method = null): NormalizeAggregation
{
return new NormalizeAggregation($name, $bucketsPath, $method);
}
}
1 change: 1 addition & 0 deletions src/QueryBuilder/Version/Version700.php
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,7 @@ class Version700 extends Version
'serial_diff',
'weighted_avg',
'composite',
'normalize',
];

protected $suggesters = [
Expand Down
128 changes: 128 additions & 0 deletions tests/Aggregation/NormalizeAggregationTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
<?php

namespace Elastica\Test\Aggregation;

use Elastica\Aggregation\DateHistogram;
use Elastica\Aggregation\NormalizeAggregation;
use Elastica\Aggregation\Sum;
use Elastica\Document;
use Elastica\Exception\InvalidException;
use Elastica\Index;
use Elastica\Query;

/**
* @internal
*/
class NormalizeAggregationTest extends BaseAggregationTest
{
/**
* @group unit
*/
public function testToArray(): void
{
$expected = [
'date_histogram' => [
'field' => 'date',
'interval' => 'day',
],
'aggs' => [
'sum_agg' => [
'sum' => [
'field' => 'value',
],
],
'normalize_agg' => [
'normalize' => [
'buckets_path' => 'sum_agg',
'method' => 'percent_of_sum',
'format' => '00.00%',
],
],
],
];

$dateHistogramAgg = new DateHistogram('histogram_agg', 'date', 'day');

$sumAgg = new Sum('sum_agg');
$sumAgg->setField('value');
$dateHistogramAgg->addAggregation($sumAgg);

$normalizeAgg = new NormalizeAggregation('normalize_agg', 'sum_agg', 'percent_of_sum');
$normalizeAgg->setFormat('00.00%');
$dateHistogramAgg->addAggregation($normalizeAgg);

$this->assertEquals($expected, $dateHistogramAgg->toArray());
}

/**
* @group unit
*/
public function testToArrayInvalidBucketsPath(): void
{
$this->expectException(InvalidException::class);

$normalizeAgg = new NormalizeAggregation('normalize_agg');
$normalizeAgg->toArray();
}

/**
* @group unit
*/
public function testToArrayInvalidMethod(): void
{
$this->expectException(InvalidException::class);

$normalizeAgg = new NormalizeAggregation('normalize_agg', 'agg');
$normalizeAgg->toArray();
}

/**
* @group functional
*/
public function testNormalizeAggregation(): void
{
$this->_checkVersion('7.9');

$index = $this->_getIndexForTest();

$dateHistogramAgg = new DateHistogram('histogram_agg', 'date', 'day');
$dateHistogramAgg->setFormat('yyyy-MM-dd');

$sumAgg = new Sum('sum_agg');
$sumAgg->setField('value');
$dateHistogramAgg->addAggregation($sumAgg);

$normalizeAgg = new NormalizeAggregation('normalize_agg', 'sum_agg', 'percent_of_sum');
$normalizeAgg->setFormat('00.00%');
$dateHistogramAgg->addAggregation($normalizeAgg);

$query = new Query();
$query->addAggregation($dateHistogramAgg);

$dateHistogramAggResult = $index->search($query)->getAggregation('histogram_agg')['buckets'];

$this->assertCount(3, $dateHistogramAggResult);

$this->assertEquals('14.29%', $dateHistogramAggResult[0]['normalize_agg']['value_as_string']);
$this->assertEquals('57.14%', $dateHistogramAggResult[1]['normalize_agg']['value_as_string']);
$this->assertEquals('28.57%', $dateHistogramAggResult[2]['normalize_agg']['value_as_string']);
}

protected function _getIndexForTest(): Index
{
$index = $this->_createIndex();

$index->addDocuments([
new Document(1, ['date' => '2018-12-01T01:00:00', 'value' => 1]),
new Document(2, ['date' => '2018-12-01T10:00:00', 'value' => 2]),
new Document(3, ['date' => '2018-12-02T02:00:00', 'value' => 3]),
new Document(4, ['date' => '2018-12-02T15:00:00', 'value' => 4]),
new Document(5, ['date' => '2018-12-02T20:00:00', 'value' => 5]),
new Document(6, ['date' => '2018-12-03T03:00:00', 'value' => 6]),
]);

$index->refresh();

return $index;
}
}
1 change: 1 addition & 0 deletions tests/QueryBuilder/DSL/AggregationTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ public function testInterface(): void
$this->_assertImplemented($aggregationDSL, 'min', Aggregation\Min::class, ['name']);
$this->_assertImplemented($aggregationDSL, 'missing', Aggregation\Missing::class, ['name', 'field']);
$this->_assertImplemented($aggregationDSL, 'nested', Aggregation\Nested::class, ['name', 'path']);
$this->_assertImplemented($aggregationDSL, 'normalize', Aggregation\NormalizeAggregation::class, ['name']);
$this->_assertImplemented($aggregationDSL, 'percentiles', Aggregation\Percentiles::class, ['name']);
$this->_assertImplemented($aggregationDSL, 'percentiles_bucket', Aggregation\PercentilesBucket::class, ['name']);
$this->_assertImplemented($aggregationDSL, 'range', Aggregation\Range::class, ['name']);
Expand Down

0 comments on commit dd88070

Please sign in to comment.