From ea3502b8bb82c20fd99c9522629f3ad0abdb0c1c Mon Sep 17 00:00:00 2001 From: Romain Neutron Date: Wed, 22 Apr 2020 09:42:25 +0200 Subject: [PATCH] Add WeightedAvg aggregation (#1771) This aggregation type has been introduced in elasticsearch 6.4, see https://www.elastic.co/guide/en/elasticsearch/reference/6.4/search-aggregations-metrics-weight-avg-aggregation.html --- CHANGELOG.md | 2 + src/Aggregation/WeightedAvg.php | 110 ++++++++++++++++++++++++++ tests/Aggregation/WeightedAvgTest.php | 100 +++++++++++++++++++++++ 3 files changed, 212 insertions(+) create mode 100644 src/Aggregation/WeightedAvg.php create mode 100644 tests/Aggregation/WeightedAvgTest.php diff --git a/CHANGELOG.md b/CHANGELOG.md index f086b2ae9e..65bf1693bb 100755 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -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 diff --git a/src/Aggregation/WeightedAvg.php b/src/Aggregation/WeightedAvg.php new file mode 100644 index 0000000000..93d091824e --- /dev/null +++ b/src/Aggregation/WeightedAvg.php @@ -0,0 +1,110 @@ +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); + } +} diff --git a/tests/Aggregation/WeightedAvgTest.php b/tests/Aggregation/WeightedAvgTest.php new file mode 100644 index 0000000000..0bb57e139c --- /dev/null +++ b/tests/Aggregation/WeightedAvgTest.php @@ -0,0 +1,100 @@ +_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; + } +}