From c69a1f286adaa04d242f6f7e0893398a163dcd49 Mon Sep 17 00:00:00 2001 From: im-denisenko Date: Wed, 18 Feb 2015 19:19:23 +0300 Subject: [PATCH] Added support for percentiles aggregation --- changes.txt | 3 + lib/Elastica/Aggregation/Percentiles.php | 56 ++++++++++ lib/Elastica/QueryBuilder/DSL/Aggregation.php | 11 +- .../Test/Aggregation/PercentilesTest.php | 104 ++++++++++++++++++ 4 files changed, 170 insertions(+), 4 deletions(-) create mode 100644 lib/Elastica/Aggregation/Percentiles.php create mode 100644 test/lib/Elastica/Test/Aggregation/PercentilesTest.php diff --git a/changes.txt b/changes.txt index 8a6e63fcd1..d976c2c904 100644 --- a/changes.txt +++ b/changes.txt @@ -1,5 +1,8 @@ CHANGES +2015-02-18 +- Added support for percentiles aggregation + 2015-02-17 - Release v1.4.3.0 - Added Elastica\Query\MatchPhrase #599 diff --git a/lib/Elastica/Aggregation/Percentiles.php b/lib/Elastica/Aggregation/Percentiles.php new file mode 100644 index 0000000000..bca904738c --- /dev/null +++ b/lib/Elastica/Aggregation/Percentiles.php @@ -0,0 +1,56 @@ +setField($field); + } + } + + /** + * Set compression parameter + * + * @param float $value + * @return $this + */ + public function setCompression($value) + { + return $this->setParam('compression', (float) $value); + } + + /** + * Set which percents must be returned + * + * @param float[] $percents + * @return $this + */ + public function setPercents(array $percents) + { + return $this->setParam('percents', $percents); + } + + /** + * Add yet another percent to result + * + * @param float $percent + * @return $this + */ + public function addPercent($percent) + { + return $this->addParam('percents', (float) $percent); + } +} diff --git a/lib/Elastica/QueryBuilder/DSL/Aggregation.php b/lib/Elastica/QueryBuilder/DSL/Aggregation.php index e7a4dae51a..29892f5727 100644 --- a/lib/Elastica/QueryBuilder/DSL/Aggregation.php +++ b/lib/Elastica/QueryBuilder/DSL/Aggregation.php @@ -18,6 +18,7 @@ use Elastica\Aggregation\Min; use Elastica\Aggregation\Missing; use Elastica\Aggregation\Nested; +use Elastica\Aggregation\Percentiles; use Elastica\Aggregation\Range; use Elastica\Aggregation\ReverseNested; use Elastica\Aggregation\ScriptedMetric; @@ -138,11 +139,13 @@ public function value_count($name, $field) * percentiles aggregation * * @link http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/search-aggregations-metrics-percentile-aggregation.html - * @param string $name + * @param string $name the name of this aggregation + * @param string $field the field on which to perform this aggregation + * @return Percentiles */ - public function percentiles($name) + public function percentiles($name, $field = null) { - throw new NotImplementedException(); + return new Percentiles($name, $field); } /** @@ -241,7 +244,7 @@ public function filter($name, AbstractFilter $filter) * filters aggregation * * @link http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/search-aggregations-bucket-filters-aggregation.html - * @param string $name + * @param string $name * @return Filters */ public function filters($name) diff --git a/test/lib/Elastica/Test/Aggregation/PercentilesTest.php b/test/lib/Elastica/Test/Aggregation/PercentilesTest.php new file mode 100644 index 0000000000..af4aa1736c --- /dev/null +++ b/test/lib/Elastica/Test/Aggregation/PercentilesTest.php @@ -0,0 +1,104 @@ +assertEquals('price_percentile', $aggr->getName()); + + $aggr = new Percentiles('price_percentile', 'price'); + $this->assertEquals('price', $aggr->getParam('field')); + } + + public function testSetField() + { + $aggr = new Percentiles('price_percentile'); + $aggr->setField('price'); + + $this->assertEquals('price', $aggr->getParam('field')); + $this->assertInstanceOf('Elastica\Aggregation\Percentiles', $aggr->setField('price')); + } + + public function testSetCompression() + { + $aggr = new Percentiles('price_percentile'); + $aggr->setCompression(200); + $this->assertEquals(200, $aggr->getParam('compression')); + $this->assertInstanceOf('Elastica\Aggregation\Percentiles', $aggr->setCompression(200)); + } + + public function testSetPercents() + { + $percents = array(1, 2, 3); + $aggr = new Percentiles('price_percentile'); + $aggr->setPercents($percents); + $this->assertEquals($percents, $aggr->getParam('percents')); + $this->assertInstanceOf('Elastica\Aggregation\Percentiles', $aggr->setPercents($percents)); + } + + public function testAddPercent() + { + $percents = array(1, 2, 3); + $aggr = new Percentiles('price_percentile'); + $aggr->setPercents($percents); + $this->assertEquals($percents, $aggr->getParam('percents')); + $aggr->addPercent(4); + $percents[] = 4; + $this->assertEquals($percents, $aggr->getParam('percents')); + $this->assertInstanceOf('Elastica\Aggregation\Percentiles', $aggr->addPercent(4)); + } + + public function testSetScript() + { + $script = 'doc["load_time"].value / 20'; + $aggr = new Percentiles('price_percentile'); + $aggr->setScript($script); + $this->assertEquals($script, $aggr->getParam('script')); + $this->assertInstanceOf('Elastica\Aggregation\Percentiles', $aggr->setScript($script)); + } + + public function testActualWork() + { + // prepare + $index = $this->_createIndex(); + $type = $index->getType('offer'); + $type->addDocuments(array( + new Document(1, array('price' => 100)), + new Document(2, array('price' => 200)), + new Document(3, array('price' => 300)), + new Document(4, array('price' => 400)), + new Document(5, array('price' => 500)), + new Document(6, array('price' => 600)), + new Document(7, array('price' => 700)), + new Document(8, array('price' => 800)), + new Document(9, array('price' => 900)), + new Document(10, array('price' => 1000)), + )); + $index->refresh(); + + // execute + $aggr = new Percentiles('price_percentile'); + $aggr->setField('price'); + + $query = new Query(); + $query->addAggregation($aggr); + + $resultSet = $type->search($query); + $aggrResult = $resultSet->getAggregation('price_percentile'); + + // hope it's ok to hardcode results... + $this->assertEquals(109.0, $aggrResult['values']['1.0']); + $this->assertEquals(145.0, $aggrResult['values']['5.0']); + $this->assertEquals(325.0, $aggrResult['values']['25.0']); + $this->assertEquals(550.0, $aggrResult['values']['50.0']); + $this->assertEquals(775.0, $aggrResult['values']['75.0']); + $this->assertEquals(955.0, $aggrResult['values']['95.0']); + $this->assertEquals(991.0, $aggrResult['values']['99.0']); + } +}