Skip to content

Commit

Permalink
Add WeightedAvg aggregation (#1771)
Browse files Browse the repository at this point in the history
  • Loading branch information
romainneutron committed Apr 22, 2020
1 parent 0d45eda commit ea3502b
Show file tree
Hide file tree
Showing 3 changed files with 212 additions and 0 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
## [Unreleased](https://github.com/ruflin/Elastica/compare/7.0.0-beta.4...master)
### Backward Compatibility Breaks
### Added
* Added `Elastica\Aggregation\WeightedAvg` aggregation [#1770](https://github.com/ruflin/Elastica/pull/1770)

### Changed
### Deprecated
### Removed
Expand Down
110 changes: 110 additions & 0 deletions src/Aggregation/WeightedAvg.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
<?php

namespace Elastica\Aggregation;

use Elastica\Exception\InvalidException;

/**
* Class WeightedAvg.
*
* @see https://www.elastic.co/guide/en/elasticsearch/reference/current/search-aggregations-metrics-weight-avg-aggregation.html
*/
class WeightedAvg extends AbstractAggregation
{
/**
* Set the value for this aggregation.
*
* @param mixed $missing
*
* @return $this
*/
public function setValue(string $field, $missing = null)
{
if ($this->hasParam('value') && isset($this->getParam('value')['script'])) {
throw new InvalidException('Weighted Average aggregation with a value mixing field and script is not possible.');
}

$value = ['field' => $field];

if (null !== $missing) {
$value['missing'] = $missing;
}

return $this->setParam('value', $value);
}

/**
* Set the value as a script for this aggregation.
*
* @return $this
*/
public function setValueScript(string $script)
{
if ($this->hasParam('value') && isset($this->getParam('value')['field'])) {
throw new InvalidException('Weighted Average aggregation with a value mixing field and script is not possible.');
}

return $this->setParam('value', ['script' => $script]);
}

/**
* Set the weight for this aggregation.
*
* @param mixed $missing
*
* @return $this
*/
public function setWeight(string $field, $missing = null)
{
if ($this->hasParam('weight') && isset($this->getParam('weight')['script'])) {
throw new InvalidException('Weighted Average aggregation with a weight mixing field and script is not possible.');
}

$weight = ['field' => $field];

if (null !== $missing) {
$weight['missing'] = $missing;
}

return $this->setParam('weight', $weight);
}

/**
* Set the weight as a script for this aggregation.
*
* @return $this
*/
public function setWeightScript(string $script)
{
if ($this->hasParam('weight') && isset($this->getParam('weight')['field'])) {
throw new InvalidException('Weighted Average aggregation with a weight mixing field and script is not possible.');
}

return $this->setParam('weight', ['script' => $script]);
}

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

/**
* Set the value_type for this aggregation.
*
* @param string $format
* @param mixed $valueType
*
* @return $this
*/
public function setValueType($valueType)
{
return $this->setParam('value_type', $valueType);
}
}
100 changes: 100 additions & 0 deletions tests/Aggregation/WeightedAvgTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
<?php

namespace Elastica\Test\Aggregation;

use Elastica\Aggregation\WeightedAvg;
use Elastica\Document;
use Elastica\Exception\InvalidException;
use Elastica\Index;
use Elastica\Query;

/**
* @internal
*/
class WeightedAvgTest extends BaseAggregationTest
{
/**
* @group functional
*/
public function testWeightedAvgAggregation(): void
{
$this->_checkVersion('6.4');

$agg = new WeightedAvg('weighted');
$agg->setValue('price');
$weightWhenMissing = 2;
$agg->setWeight('weight', $weightWhenMissing);

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

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

$this->assertTrue($resultSet->hasAggregations());
$this->assertEquals((5 * 3 + 8 + 1 + 3 * $weightWhenMissing) / 7.0, $results['weighted']['value']);
}

/**
* @group unit
*/
public function testItsNotPossibleToMixValueFieldAndScript(): void
{
$agg = new WeightedAvg('weighted');
$agg->setValue('price');

$this->expectExceptionObject(new InvalidException('Weighted Average aggregation with a value mixing field and script is not possible.'));
$agg->setValueScript('doc.price.value + 1');
}

/**
* @group unit
*/
public function testItsNotPossibleToMixValueScriptAndField(): void
{
$agg = new WeightedAvg('weighted');
$agg->setValueScript('doc.price.value + 1');

$this->expectExceptionObject(new InvalidException('Weighted Average aggregation with a value mixing field and script is not possible.'));
$agg->setValue('price');
}

/**
* @group unit
*/
public function testItsNotPossibleToMixWeightFieldAndScript(): void
{
$agg = new WeightedAvg('weighted');
$agg->setWeight('weight');

$this->expectExceptionObject(new InvalidException('Weighted Average aggregation with a weight mixing field and script is not possible.'));
$agg->setWeightScript('doc.weight.value + 1');
}

/**
* @group unit
*/
public function testItsNotPossibleToMixWeightScriptAndField(): void
{
$agg = new WeightedAvg('weighted');
$agg->setWeightScript('doc.weight.value + 1');

$this->expectExceptionObject(new InvalidException('Weighted Average aggregation with a weight mixing field and script is not possible.'));
$agg->setWeight('weight');
}

protected function _getIndexForTest(): Index
{
$index = $this->_createIndex();
$index->addDocuments([
new Document(1, ['price' => 5, 'weight' => 3]),
new Document(2, ['price' => 8, 'weight' => 1]),
new Document(3, ['price' => 1, 'weight' => 1]),
new Document(4, ['price' => 3]),
]);

$index->refresh();

return $index;
}
}

0 comments on commit ea3502b

Please sign in to comment.