From 19e86154654bbe57697d8c2cab2ee6083480e4f5 Mon Sep 17 00:00:00 2001 From: Romain Neutron Date: Wed, 22 Apr 2020 15:25:45 +0200 Subject: [PATCH] Backport Weighted average aggregation in 6.x (#1773) This is a backport of #1771 in branch 6.x --- CHANGELOG.md | 3 + lib/Elastica/Aggregation/WeightedAvg.php | 109 ++++++++++++++++++ test/Elastica/Aggregation/WeightedAvgTest.php | 97 ++++++++++++++++ 3 files changed, 209 insertions(+) create mode 100644 lib/Elastica/Aggregation/WeightedAvg.php create mode 100644 test/Elastica/Aggregation/WeightedAvgTest.php diff --git a/CHANGELOG.md b/CHANGELOG.md index 3018fcca8c..0c96151073 100755 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,10 +6,13 @@ All notable changes to this project will be documented in this file based on the ### Backward Compatibility Breaks ### Bugfixes + * Always set the Guzzle `base_uri` to support connecting to multiple ES hosts. [#1618](https://github.com/ruflin/Elastica/pull/1618) [#1644](https://github.com/ruflin/Elastica/issues/1644) ### Added +* Added `Elastica\Aggregation\WeightedAvg` aggregation [#1770](https://github.com/ruflin/Elastica/pull/1770) + ### Improvements ### Deprecated diff --git a/lib/Elastica/Aggregation/WeightedAvg.php b/lib/Elastica/Aggregation/WeightedAvg.php new file mode 100644 index 0000000000..c2c9765576 --- /dev/null +++ b/lib/Elastica/Aggregation/WeightedAvg.php @@ -0,0 +1,109 @@ +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 + * + * @return $this + */ + public function setValueType($valueType) + { + return $this->setParam('value_type', $valueType); + } +} diff --git a/test/Elastica/Aggregation/WeightedAvgTest.php b/test/Elastica/Aggregation/WeightedAvgTest.php new file mode 100644 index 0000000000..d7c9500d0f --- /dev/null +++ b/test/Elastica/Aggregation/WeightedAvgTest.php @@ -0,0 +1,97 @@ +_createIndex(); + + $index->getType('_doc')->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; + } + + /** + * @group functional + */ + public function testWeightedAvgAggregation() + { + $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() + { + $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() + { + $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() + { + $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() + { + $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'); + } +}