From 13a75ce959bf726477268b73a2b491f89800b1b6 Mon Sep 17 00:00:00 2001 From: Josselin Henrot Date: Fri, 26 Jan 2018 10:24:16 +0100 Subject: [PATCH] Add avg_bucket & sum_bucket to aggregations --- CHANGELOG.md | 5 +- lib/Elastica/Aggregation/AvgBucket.php | 75 ++++++++++++++++ lib/Elastica/Aggregation/SumBucket.php | 75 ++++++++++++++++ lib/Elastica/QueryBuilder/DSL/Aggregation.php | 32 +++++++ .../QueryBuilder/Version/Version240.php | 2 + test/Elastica/Aggregation/AvgBucketTest.php | 87 +++++++++++++++++++ test/Elastica/Aggregation/SumBucketTest.php | 87 +++++++++++++++++++ 7 files changed, 361 insertions(+), 2 deletions(-) create mode 100644 lib/Elastica/Aggregation/AvgBucket.php create mode 100644 lib/Elastica/Aggregation/SumBucket.php create mode 100644 test/Elastica/Aggregation/AvgBucketTest.php create mode 100644 test/Elastica/Aggregation/SumBucketTest.php diff --git a/CHANGELOG.md b/CHANGELOG.md index 4ec85bd31e..d317434966 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,7 +4,7 @@ All notable changes to this project will be documented in this file based on the ## [Unreleased](https://github.com/ruflin/Elastica/compare/5.3.0...master) ### Backward Compatibility Breaks - + ### Bugfixes ### Added @@ -23,7 +23,7 @@ All notable changes to this project will be documented in this file based on the ### Backward Compatibility Breaks - Removed `Query\NumericRange`, use `Query\Range` instead [#1334](https://github.com/ruflin/Elastica/pull/1334) - + ### Bugfixes - Send the `scroll_id` inside a json body instead of plain text [#1325](https://github.com/ruflin/Elastica/pull/1325) @@ -31,6 +31,7 @@ All notable changes to this project will be documented in this file based on the ### Added - Added getNumberOfReplicas() for index settings [PR#1324](https://github.com/ruflin/Elastica/pull/1324) - Added getNumberOfShards() for index settings [PR#1321](https://github.com/ruflin/Elastica/pull/1331) + - Added avg_bucket() and sum_bucket() in aggregations [PR#1443](https://github.com/ruflin/Elastica/pull/1443) - (https://github.com/ruflin/Elastica/issues/1279) ## [5.2.1](https://github.com/ruflin/Elastica/compare/5.2.0...5.2.1) diff --git a/lib/Elastica/Aggregation/AvgBucket.php b/lib/Elastica/Aggregation/AvgBucket.php new file mode 100644 index 0000000000..2a5a0a8ad2 --- /dev/null +++ b/lib/Elastica/Aggregation/AvgBucket.php @@ -0,0 +1,75 @@ +setBucketsPath($bucketsPath); + } + } + + /** + * Set the buckets_path for this aggregation. + * + * @param string $bucketsPath + * + * @return $this + */ + public function setBucketsPath($bucketsPath) + { + return $this->setParam('buckets_path', $bucketsPath); + } + + /** + * Set the gap policy for this aggregation. + * + * @param string $gapPolicy + * + * @return $this + */ + public function setGapPolicy($gapPolicy) + { + return $this->setParam('gap_policy', $gapPolicy); + } + + /** + * Set the format for this aggregation. + * + * @param string $format + * + * @return $this + */ + public function setFormat($format) + { + return $this->setParam('format', $format); + } + + /** + * @throws InvalidException If buckets path or script is not set + * + * @return array + */ + public function toArray() + { + if (!$this->hasParam('buckets_path')) { + throw new InvalidException('Buckets path is required'); + } + + return parent::toArray(); + } +} diff --git a/lib/Elastica/Aggregation/SumBucket.php b/lib/Elastica/Aggregation/SumBucket.php new file mode 100644 index 0000000000..eb45ecb8cc --- /dev/null +++ b/lib/Elastica/Aggregation/SumBucket.php @@ -0,0 +1,75 @@ +setBucketsPath($bucketsPath); + } + } + + /** + * Set the buckets_path for this aggregation. + * + * @param string $bucketsPath + * + * @return $this + */ + public function setBucketsPath($bucketsPath) + { + return $this->setParam('buckets_path', $bucketsPath); + } + + /** + * Set the gap policy for this aggregation. + * + * @param string $gapPolicy + * + * @return $this + */ + public function setGapPolicy($gapPolicy) + { + return $this->setParam('gap_policy', $gapPolicy); + } + + /** + * Set the format for this aggregation. + * + * @param string $format + * + * @return $this + */ + public function setFormat($format) + { + return $this->setParam('format', $format); + } + + /** + * @throws InvalidException If buckets path or script is not set + * + * @return array + */ + public function toArray() + { + if (!$this->hasParam('buckets_path')) { + throw new InvalidException('Buckets path is required'); + } + + return parent::toArray(); + } +} diff --git a/lib/Elastica/QueryBuilder/DSL/Aggregation.php b/lib/Elastica/QueryBuilder/DSL/Aggregation.php index 33612e20d9..295de94957 100644 --- a/lib/Elastica/QueryBuilder/DSL/Aggregation.php +++ b/lib/Elastica/QueryBuilder/DSL/Aggregation.php @@ -2,6 +2,7 @@ namespace Elastica\QueryBuilder\DSL; use Elastica\Aggregation\Avg; +use Elastica\Aggregation\AvgBucket; use Elastica\Aggregation\BucketScript; use Elastica\Aggregation\Cardinality; use Elastica\Aggregation\DateHistogram; @@ -26,6 +27,7 @@ use Elastica\Aggregation\SignificantTerms; use Elastica\Aggregation\Stats; use Elastica\Aggregation\Sum; +use Elastica\Aggregation\SumBucket; use Elastica\Aggregation\Terms; use Elastica\Aggregation\TopHits; use Elastica\Aggregation\ValueCount; @@ -94,6 +96,21 @@ public function sum($name) return new Sum($name); } + /** + * sum bucket aggregation. + * + * @link https://www.elastic.co/guide/en/elasticsearch/reference/current/search-aggregations-pipeline-sum-bucket-aggregation.html + * + * @param string $name + * @param array|null $bucketsPath + * + * @return SumBucket + */ + public function sum_bucket($name, $bucketsPath = null) + { + return new SumBucket($name, $bucketsPath); + } + /** * avg aggregation. * @@ -108,6 +125,21 @@ public function avg($name) return new Avg($name); } + /** + * avg bucket aggregation. + * + * @link https://www.elastic.co/guide/en/elasticsearch/reference/current/search-aggregations-pipeline-avg-bucket-aggregation.html + * + * @param string $name + * @param array|null $bucketsPath + * + * @return AvgBucket + */ + public function avg_bucket($name, $bucketsPath = null) + { + return new AvgBucket($name, $bucketsPath); + } + /** * stats aggregation. * diff --git a/lib/Elastica/QueryBuilder/Version/Version240.php b/lib/Elastica/QueryBuilder/Version/Version240.php index 4a39fd3a29..092d88a88d 100644 --- a/lib/Elastica/QueryBuilder/Version/Version240.php +++ b/lib/Elastica/QueryBuilder/Version/Version240.php @@ -53,7 +53,9 @@ class Version240 extends Version 'min', 'max', 'sum', + 'sum_bucket', 'avg', + 'avg_bucket', 'stats', 'extended_stats', 'value_count', diff --git a/test/Elastica/Aggregation/AvgBucketTest.php b/test/Elastica/Aggregation/AvgBucketTest.php new file mode 100644 index 0000000000..63237c78a4 --- /dev/null +++ b/test/Elastica/Aggregation/AvgBucketTest.php @@ -0,0 +1,87 @@ +_createIndex(); + + $index->getType('test')->addDocuments([ + Document::create(['page' => 1, 'likes' => 180]), + Document::create(['page' => 1, 'likes' => 156]), + Document::create(['page' => 2, 'likes' => 155]), + ]); + + $index->refresh(); + + return $index; + } + + /** + * @group functional + */ + public function testAvgBucketAggregation() + { + $this->_checkScriptInlineSetting(); + + $avgBucketAggregation = new AvgBucket( + 'avg_likes_by_page', + 'pages > avg_likes' + ); + + $sumLikes = new Avg('avg_likes'); + $sumLikes->setField('likes'); + + $groupByPage = new Terms('pages'); + $groupByPage + ->setField('page') + ->setSize(2) + ->addAggregation($sumLikes); + + $query = Query::create([])->addAggregation($groupByPage)->addAggregation($avgBucketAggregation); + + $results = $this->_getIndexForTest()->search($query)->getAggregation('avg_likes_by_page'); + + $this->assertEquals(161.5, $results['value']); + } + + /** + * @group unit + */ + public function testConstructThroughSetters() + { + $serialDiffAgg = new AvgBucket('avg_bucket'); + + $serialDiffAgg + ->setBucketsPath('pages > avg_likes_by_page') + ->setFormat('test_format') + ->setGapPolicy(10); + + $expected = [ + 'avg_bucket' => [ + 'buckets_path' => 'pages > avg_likes_by_page', + 'format' => 'test_format', + 'gap_policy' => 10, + ], + ]; + + $this->assertEquals($expected, $serialDiffAgg->toArray()); + } + + /** + * @group unit + * @expectedException InvalidException + */ + public function testToArrayInvalidBucketsPath() + { + $serialDiffAgg = new AvgBucket('avg_bucket'); + $serialDiffAgg->toArray(); + } +} diff --git a/test/Elastica/Aggregation/SumBucketTest.php b/test/Elastica/Aggregation/SumBucketTest.php new file mode 100644 index 0000000000..f4ec22008c --- /dev/null +++ b/test/Elastica/Aggregation/SumBucketTest.php @@ -0,0 +1,87 @@ +_createIndex(); + + $index->getType('test')->addDocuments([ + Document::create(['page' => 1, 'likes' => 180]), + Document::create(['page' => 1, 'likes' => 156]), + Document::create(['page' => 2, 'likes' => 155]), + ]); + + $index->refresh(); + + return $index; + } + + /** + * @group functional + */ + public function testAvgBucketAggregation() + { + $this->_checkScriptInlineSetting(); + + $sumBucketAggregation = new SumBucket( + 'sum_likes_by_page', + 'pages > sum_likes' + ); + + $sumLikes = new Sum('sum_likes'); + $sumLikes->setField('likes'); + + $groupByPage = new Terms('pages'); + $groupByPage + ->setField('page') + ->setSize(2) + ->addAggregation($sumLikes); + + $query = Query::create([])->addAggregation($groupByPage)->addAggregation($sumBucketAggregation); + + $results = $this->_getIndexForTest()->search($query)->getAggregation('sum_likes_by_page'); + + $this->assertEquals(491, $results['value']); + } + + /** + * @group unit + */ + public function testConstructThroughSetters() + { + $serialDiffAgg = new SumBucket('sum_bucket'); + + $serialDiffAgg + ->setBucketsPath('pages > sum_likes_by_page') + ->setFormat('test_format') + ->setGapPolicy(10); + + $expected = [ + 'avg_bucket' => [ + 'buckets_path' => 'pages > sum_likes_by_page', + 'format' => 'test_format', + 'gap_policy' => 10, + ], + ]; + + $this->assertEquals($expected, $serialDiffAgg->toArray()); + } + + /** + * @group unit + * @expectedException InvalidException + */ + public function testToArrayInvalidBucketsPath() + { + $serialDiffAgg = new SumBucket('sum_bucket'); + $serialDiffAgg->toArray(); + } +}