Skip to content

Commit 29b62a7

Browse files
committed
Merge pull request #773 from bakura10/filters
Add support for filters aggregation
2 parents 0db1e7e + ac302eb commit 29b62a7

File tree

3 files changed

+173
-1
lines changed

3 files changed

+173
-1
lines changed

lib/Elastica/Aggregation/Filters.php

+59
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
<?php
2+
3+
namespace Elastica\Aggregation;
4+
5+
use Elastica\Filter\AbstractFilter;
6+
7+
/**
8+
* Class Filters
9+
* @package Elastica\Aggregation
10+
* @link http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/search-aggregations-bucket-filters-aggregation.html
11+
*/
12+
class Filters extends AbstractAggregation
13+
{
14+
/**
15+
* Add a filter
16+
*
17+
* If a name is given, it will be added as a key, otherwise considered as an anonymous filter
18+
*
19+
* @param AbstractFilter $filter
20+
* @param string $name
21+
* @return Filters
22+
*/
23+
public function addFilter(AbstractFilter $filter, $name = '')
24+
{
25+
if (empty($name)) {
26+
$filterArray[] = $filter->toArray();
27+
} else {
28+
$filterArray[$name] = $filter->toArray();
29+
}
30+
31+
return $this->addParam('filters', $filterArray);
32+
}
33+
34+
/**
35+
* @return array
36+
*/
37+
public function toArray()
38+
{
39+
$array = array();
40+
$filters = $this->getParam('filters');
41+
42+
foreach ($filters as $filter) {
43+
// Detect between anonymous filters and named ones
44+
$key = key($filter);
45+
46+
if (is_string($key)) {
47+
$array['filters']['filters'][$key] = current($filter);
48+
} else {
49+
$array['filters']['filters'][] = current($filter);
50+
}
51+
}
52+
53+
if ($this->_aggs) {
54+
$array['aggs'] = $this->_aggs;
55+
}
56+
57+
return $array;
58+
}
59+
}

lib/Elastica/QueryBuilder/DSL/Aggregation.php

+3-1
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
use Elastica\Aggregation\DateRange;
99
use Elastica\Aggregation\ExtendedStats;
1010
use Elastica\Aggregation\Filter as FilterAggregation;
11+
use Elastica\Aggregation\Filters;
1112
use Elastica\Aggregation\GeoDistance;
1213
use Elastica\Aggregation\GeohashGrid;
1314
use Elastica\Aggregation\GlobalAggregation;
@@ -233,10 +234,11 @@ public function filter($name, AbstractFilter $filter)
233234
*
234235
* @link http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/search-aggregations-bucket-filters-aggregation.html
235236
* @param string $name
237+
* @return Filters
236238
*/
237239
public function filters($name)
238240
{
239-
throw new NotImplementedException();
241+
return new Filters($name);
240242
}
241243

242244
/**
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,111 @@
1+
<?php
2+
3+
namespace Elastica\Test\Aggregation;
4+
5+
use Elastica\Aggregation\Avg;
6+
use Elastica\Aggregation\Filter;
7+
use Elastica\Aggregation\Filters;
8+
use Elastica\Document;
9+
use Elastica\Filter\Range;
10+
use Elastica\Filter\Term;
11+
use Elastica\Query;
12+
13+
class FiltersTest extends BaseAggregationTest
14+
{
15+
protected function setUp()
16+
{
17+
parent::setUp();
18+
$this->_index = $this->_createIndex("filter");
19+
$docs = array(
20+
new Document("1", array("price" => 5, "color" => "blue")),
21+
new Document("2", array("price" => 8, "color" => "blue")),
22+
new Document("3", array("price" => 1, "color" => "red")),
23+
new Document("4", array("price" => 3, "color" => "green")),
24+
);
25+
$this->_index->getType("test")->addDocuments($docs);
26+
$this->_index->refresh();
27+
}
28+
29+
public function testToArrayUsingNamedFilters()
30+
{
31+
$expected = array(
32+
"filters" => array(
33+
"filters" => array(
34+
"blue" => array(
35+
"term" => array("color" => "blue")
36+
),
37+
"red" => array(
38+
"term" => array("color" => "red")
39+
)
40+
)
41+
),
42+
"aggs" => array(
43+
"avg_price" => array("avg" => array("field" => "price")),
44+
),
45+
);
46+
47+
$agg = new Filters("by_color");
48+
$agg->addFilter(new Term(array('color' => 'blue')), 'blue');
49+
$agg->addFilter(new Term(array('color' => 'red')), 'red');
50+
51+
$avg = new Avg("avg_price");
52+
$avg->setField("price");
53+
$agg->addAggregation($avg);
54+
55+
$this->assertEquals($expected, $agg->toArray());
56+
}
57+
58+
public function testToArrayUsingAnonymousFilters()
59+
{
60+
$expected = array(
61+
"filters" => array(
62+
"filters" => array(
63+
array(
64+
"term" => array("color" => "blue")
65+
),
66+
array(
67+
"term" => array("color" => "red")
68+
)
69+
)
70+
),
71+
"aggs" => array(
72+
"avg_price" => array("avg" => array("field" => "price")),
73+
),
74+
);
75+
76+
$agg = new Filters("by_color");
77+
$agg->addFilter(new Term(array("color" => "blue")));
78+
$agg->addFilter(new Term(array("color" => "red")));
79+
80+
$avg = new Avg("avg_price");
81+
$avg->setField("price");
82+
$agg->addAggregation($avg);
83+
84+
$this->assertEquals($expected, $agg->toArray());
85+
}
86+
87+
public function testFilterAggregation()
88+
{
89+
$agg = new Filters("by_color");
90+
$agg->addFilter(new Term(array('color' => 'blue')), 'blue');
91+
$agg->addFilter(new Term(array('color' => 'red')), 'red');
92+
93+
$avg = new Avg("avg_price");
94+
$avg->setField("price");
95+
$agg->addAggregation($avg);
96+
97+
$query = new Query();
98+
$query->addAggregation($agg);
99+
100+
$results = $this->_index->search($query)->getAggregation("by_color");
101+
102+
$resultsForBlue = $results["buckets"]["blue"];
103+
$resultsForRed = $results["buckets"]["red"];
104+
105+
$this->assertEquals(2, $resultsForBlue["doc_count"]);
106+
$this->assertEquals(1, $resultsForRed["doc_count"]);
107+
108+
$this->assertEquals((5 + 8) / 2, $resultsForBlue["avg_price"]["value"]);
109+
$this->assertEquals(1, $resultsForRed["avg_price"]["value"]);
110+
}
111+
}

0 commit comments

Comments
 (0)