Skip to content

Commit

Permalink
Add "missing" behavior to some aggregations
Browse files Browse the repository at this point in the history
  • Loading branch information
romainneutron committed Nov 24, 2020
1 parent 11ababf commit ef1b8e5
Show file tree
Hide file tree
Showing 25 changed files with 273 additions and 12 deletions.
12 changes: 12 additions & 0 deletions CHANGELOG.md
Expand Up @@ -7,6 +7,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
## [Unreleased](https://github.com/ruflin/Elastica/compare/7.0.0...master)
### Backward Compatibility Breaks
* Allow the Terms query to accept arrays of strings, ints and floats [#1872](https://github.com/ruflin/Elastica/pull/1872)
* Added a default value to `Elastica\Aggregation\Percentiles::setMissing()` [#1875](https://github.com/ruflin/Elastica/pull/1875)
### Added
* Ability to specify the type of authentication manually by the `auth_type` parameter (in the client class config) was added (allowed values are `basic, digest, gssnegotiate, ntlm`)
* Added `if_seq_no` / `if_primary_term` to replace `version` for [optimistic concurrency control](https://www.elastic.co/guide/en/elasticsearch/reference/6.8/optimistic-concurrency-control.html)
Expand All @@ -23,6 +24,17 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
* Added `static_lambda` CS rule [#1870](https://github.com/ruflin/Elastica/pull/1870)
* Added `Elastica\Aggregation\DateRange::setTimezone()` [#1847](https://github.com/ruflin/Elastica/pull/1847)
* Added endpoint options support to `Elastica\Index::create()` [#1859](https://github.com/ruflin/Elastica/pull/1859)
* Added `Elastica\Aggregation\Avg::setMissing()` [#1876](https://github.com/ruflin/Elastica/pull/1876)
* Added `Elastica\Aggregation\Cardinality::setMissing()` [#1876](https://github.com/ruflin/Elastica/pull/1876)
* Added `Elastica\Aggregation\DateRange::setMissing()` [#1876](https://github.com/ruflin/Elastica/pull/1876)
* Added `Elastica\Aggregation\DateHistogram::setMissing()` [#1876](https://github.com/ruflin/Elastica/pull/1876)
* Added `Elastica\Aggregation\ExtendedStats::setMissing()` [#1876](https://github.com/ruflin/Elastica/pull/1876)
* Added `Elastica\Aggregation\Histogram::setMissing()` [#1876](https://github.com/ruflin/Elastica/pull/1876)
* Added `Elastica\Aggregation\Max::setMissing()` [#1876](https://github.com/ruflin/Elastica/pull/1876)
* Added `Elastica\Aggregation\Min::setMissing()` [#1876](https://github.com/ruflin/Elastica/pull/1876)
* Added `Elastica\Aggregation\Stats::setMissing()` [#1876](https://github.com/ruflin/Elastica/pull/1876)
* Added `Elastica\Aggregation\Sum::setMissing()` [#1876](https://github.com/ruflin/Elastica/pull/1876)
* Added `Elastica\Aggregation\Terms::setMissing()` [#1876](https://github.com/ruflin/Elastica/pull/1876)
### Changed
* Allow `string` such as `wait_for` to be passed to `AbstractUpdateAction::setRefresh` [#1791](https://github.com/ruflin/Elastica/pull/1791)
* Changed the return type of `AbstractUpdateAction::getRefresh` to `boolean|string` [#1791](https://github.com/ruflin/Elastica/pull/1791)
Expand Down
1 change: 1 addition & 0 deletions src/Aggregation/Avg.php
Expand Up @@ -9,4 +9,5 @@
*/
class Avg extends AbstractSimpleAggregation
{
use MissingTrait;
}
2 changes: 2 additions & 0 deletions src/Aggregation/Cardinality.php
Expand Up @@ -9,6 +9,8 @@
*/
class Cardinality extends AbstractSimpleAggregation
{
use MissingTrait;

public const DEFAULT_PRECISION_THRESHOLD_VALUE = 3000;

/**
Expand Down
2 changes: 2 additions & 0 deletions src/Aggregation/DateRange.php
Expand Up @@ -9,6 +9,8 @@
*/
class DateRange extends Range
{
use MissingTrait;

/**
* Set the formatting for the returned date values.
*
Expand Down
1 change: 1 addition & 0 deletions src/Aggregation/ExtendedStats.php
Expand Up @@ -9,4 +9,5 @@
*/
class ExtendedStats extends AbstractSimpleAggregation
{
use MissingTrait;
}
2 changes: 2 additions & 0 deletions src/Aggregation/Histogram.php
Expand Up @@ -9,6 +9,8 @@
*/
class Histogram extends AbstractSimpleAggregation
{
use MissingTrait;

/**
* @param string $name the name of this aggregation
* @param string $field the name of the field on which to perform the aggregation
Expand Down
1 change: 1 addition & 0 deletions src/Aggregation/Max.php
Expand Up @@ -9,4 +9,5 @@
*/
class Max extends AbstractSimpleAggregation
{
use MissingTrait;
}
1 change: 1 addition & 0 deletions src/Aggregation/Min.php
Expand Up @@ -9,4 +9,5 @@
*/
class Min extends AbstractSimpleAggregation
{
use MissingTrait;
}
18 changes: 18 additions & 0 deletions src/Aggregation/MissingTrait.php
@@ -0,0 +1,18 @@
<?php

namespace Elastica\Aggregation;

trait MissingTrait
{
/**
* Defines how documents that are missing a value should be treated.
*
* @param mixed $missing
*
* @return $this
*/
public function setMissing($missing): self
{
return $this->setParam('missing', $missing);
}
}
13 changes: 2 additions & 11 deletions src/Aggregation/Percentiles.php
Expand Up @@ -9,6 +9,8 @@
*/
class Percentiles extends AbstractSimpleAggregation
{
use MissingTrait;

/**
* @param string $name the name of this aggregation
* @param string $field the field on which to perform this aggregation
Expand Down Expand Up @@ -79,15 +81,4 @@ public function addPercent(float $percent): self
{
return $this->addParam('percents', $percent);
}

/**
* Defines how documents that are missing a value should
* be treated.
*
* @return $this
*/
public function setMissing(float $missing): self
{
return $this->setParam('missing', $missing);
}
}
2 changes: 1 addition & 1 deletion src/Aggregation/Range.php
Expand Up @@ -58,7 +58,7 @@ public function setKeyed(bool $keyed): self
/**
* @return $this
*
* @deprecated singe version 7.1.0, use the "setKeyed()" method instead.
* @deprecated since version 7.1.0, use the "setKeyed()" method instead.
*/
public function setKeyedResponse(bool $keyed = true): self
{
Expand Down
1 change: 1 addition & 0 deletions src/Aggregation/Stats.php
Expand Up @@ -9,4 +9,5 @@
*/
class Stats extends AbstractSimpleAggregation
{
use MissingTrait;
}
1 change: 1 addition & 0 deletions src/Aggregation/Sum.php
Expand Up @@ -9,4 +9,5 @@
*/
class Sum extends AbstractSimpleAggregation
{
use MissingTrait;
}
2 changes: 2 additions & 0 deletions src/Aggregation/Terms.php
Expand Up @@ -9,6 +9,8 @@
*/
class Terms extends AbstractTermsAggregation
{
use MissingTrait;

/**
* Set the bucket sort order.
*
Expand Down
20 changes: 20 additions & 0 deletions tests/Aggregation/AvgTest.php
Expand Up @@ -30,6 +30,25 @@ public function testAvgAggregation(): void
$this->assertEquals((5 + 8 + 1 + 3) / 4.0, $results['avg']['value']);
}

/**
* @group functional
*/
public function testAvgAggregationWithMissingValue(): void
{
$agg = new Avg('avg');
$agg->setField('price');
$agg->setMissing(72);

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

$resultSet = $this->_getIndexForTest()->search($query);
$results = $resultSet->getAggregations();

$this->assertTrue($resultSet->hasAggregations());
$this->assertEquals((5 + 8 + 1 + 3 + 72) / 5.0, $results['avg']['value']);
}

protected function _getIndexForTest(): Index
{
$index = $this->_createIndex();
Expand All @@ -39,6 +58,7 @@ protected function _getIndexForTest(): Index
new Document(2, ['price' => 8]),
new Document(3, ['price' => 1]),
new Document(4, ['price' => 3]),
new Document(5, ['anything' => 'anything']),
]);

$index->refresh();
Expand Down
17 changes: 17 additions & 0 deletions tests/Aggregation/CardinalityTest.php
Expand Up @@ -28,6 +28,22 @@ public function testCardinalityAggregation(): void
$this->assertEquals(3, $results['value']);
}

/**
* @group functional
*/
public function testCardinalityAggregationWithMissing(): void
{
$agg = new Cardinality('cardinality');
$agg->setField('color');
$agg->setMissing('yellow');

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

$this->assertEquals(4, $results['value']);
}

public function validPrecisionThresholdProvider()
{
return [
Expand Down Expand Up @@ -88,6 +104,7 @@ protected function _getIndexForTest(): Index
new Document(2, ['color' => 'blue']),
new Document(3, ['color' => 'red']),
new Document(4, ['color' => 'green']),
new Document(5, ['anything' => 'anything']),
]);

$index->refresh();
Expand Down
28 changes: 28 additions & 0 deletions tests/Aggregation/DateHistogramTest.php
Expand Up @@ -39,6 +39,33 @@ public function testDateHistogramAggregation(): void
$this->assertEquals(1, $nonDocCount);
}

/**
* @group functional
*/
public function testDateHistogramAggregationWithMissing(): void
{
$agg = new DateHistogram('hist', 'created', '1h');
$agg->setMissing('2014-01-29T04:20:00');

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

$docCount = 0;
$nonDocCount = 0;
foreach ($results['buckets'] as $bucket) {
if (1 == $bucket['doc_count']) {
++$docCount;
} else {
++$nonDocCount;
}
}
// 3 Documents that were added
$this->assertEquals(4, $docCount);
// 1 document that was generated in between for the missing hour
$this->assertEquals(1, $nonDocCount);
}

/**
* @group unit
*/
Expand Down Expand Up @@ -111,6 +138,7 @@ protected function _getIndexForTest(): Index
new Document(1, ['created' => '2014-01-29T00:20:00']),
new Document(2, ['created' => '2014-01-29T02:20:00']),
new Document(3, ['created' => '2014-01-29T03:20:00']),
new Document(4, ['anything' => 'anything']),
]);

$index->refresh();
Expand Down
24 changes: 24 additions & 0 deletions tests/Aggregation/DateRangeTest.php
Expand Up @@ -56,6 +56,29 @@ public function testDateRangeAggregation(): void
}
}

/**
* @group functional
*/
public function testDateRangeAggregationWithMissing(): void
{
$agg = new DateRange('date');
$agg->setField('created');
$agg->addRange(1390958535000)->addRange(null, 1390958535000);
$agg->setMissing(1390958534000);

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

foreach ($results['buckets'] as $bucket) {
if (\array_key_exists('to', $bucket)) {
$this->assertEquals(2, $bucket['doc_count']);
} elseif (\array_key_exists('from', $bucket)) {
$this->assertEquals(2, $bucket['doc_count']);
}
}
}

/**
* @group functional
*/
Expand Down Expand Up @@ -108,6 +131,7 @@ protected function _getIndexForTest(): Index
new Document(1, ['created' => 1390962135000]),
new Document(2, ['created' => 1390965735000]),
new Document(3, ['created' => 1390954935000]),
new Document(4, ['anything' => 'anything']),
]);

$index->refresh();
Expand Down
22 changes: 22 additions & 0 deletions tests/Aggregation/ExtendedStatsTest.php
Expand Up @@ -32,6 +32,27 @@ public function testExtendedStatsAggregation(): void
$this->assertArrayHasKey('sum_of_squares', $results);
}

/**
* @group functional
*/
public function testExtendedStatsAggregationWithMissing(): void
{
$agg = new ExtendedStats('stats');
$agg->setField('price');
$agg->setMissing(10);

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

$this->assertEquals(5, $results['count']);
$this->assertEquals(1, $results['min']);
$this->assertEquals(10, $results['max']);
$this->assertEquals((5 + 8 + 1 + 3 + 10) / 5.0, $results['avg']);
$this->assertEquals((5 + 8 + 1 + 3 + 10), $results['sum']);
$this->assertArrayHasKey('sum_of_squares', $results);
}

protected function _getIndexForTest(): Index
{
$index = $this->_createIndex();
Expand All @@ -41,6 +62,7 @@ protected function _getIndexForTest(): Index
new Document(2, ['price' => 8]),
new Document(3, ['price' => 1]),
new Document(4, ['price' => 3]),
new Document(5, ['anything' => 'anything']),
]);

$index->refresh();
Expand Down
20 changes: 20 additions & 0 deletions tests/Aggregation/HistogramTest.php
Expand Up @@ -30,6 +30,25 @@ public function testHistogramAggregation(): void
$this->assertEquals(2, $buckets[3]['doc_count']);
}

/**
* @group functional
*/
public function testHistogramAggregationWithMissing(): void
{
$agg = new Histogram('hist', 'price', 10);
$agg->setMinimumDocumentCount(0); // should return empty buckets
$agg->setMissing(37);

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

$buckets = $results['buckets'];
$this->assertCount(5, $buckets);
$this->assertEquals(30, $buckets[3]['key']);
$this->assertEquals(3, $buckets[3]['doc_count']);
}

protected function _getIndexForTest(): Index
{
$index = $this->_createIndex();
Expand All @@ -43,6 +62,7 @@ protected function _getIndexForTest(): Index
new Document(6, ['price' => 35, 'color' => 'green']),
new Document(7, ['price' => 42, 'color' => 'red']),
new Document(8, ['price' => 41, 'color' => 'blue']),
new Document(9, ['color' => 'yellow']),
]);

$index->refresh();
Expand Down

0 comments on commit ef1b8e5

Please sign in to comment.