Skip to content

Commit

Permalink
Add support for filters aggregation
Browse files Browse the repository at this point in the history
  • Loading branch information
bakura10 committed Feb 10, 2015
1 parent c8c546e commit ac302eb
Show file tree
Hide file tree
Showing 3 changed files with 173 additions and 1 deletion.
59 changes: 59 additions & 0 deletions lib/Elastica/Aggregation/Filters.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
<?php

namespace Elastica\Aggregation;

use Elastica\Filter\AbstractFilter;

/**
* Class Filters
* @package Elastica\Aggregation
* @link http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/search-aggregations-bucket-filters-aggregation.html
*/
class Filters extends AbstractAggregation
{
/**
* Add a filter
*
* If a name is given, it will be added as a key, otherwise considered as an anonymous filter
*
* @param AbstractFilter $filter
* @param string $name
* @return Filters
*/
public function addFilter(AbstractFilter $filter, $name = '')
{
if (empty($name)) {
$filterArray[] = $filter->toArray();
} else {
$filterArray[$name] = $filter->toArray();
}

return $this->addParam('filters', $filterArray);
}

/**
* @return array
*/
public function toArray()
{
$array = array();
$filters = $this->getParam('filters');

foreach ($filters as $filter) {
// Detect between anonymous filters and named ones
$key = key($filter);

if (is_string($key)) {
$array['filters']['filters'][$key] = current($filter);
} else {
$array['filters']['filters'][] = current($filter);
}
}

if ($this->_aggs) {
$array['aggs'] = $this->_aggs;
}

return $array;
}
}
4 changes: 3 additions & 1 deletion lib/Elastica/QueryBuilder/DSL/Aggregation.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
use Elastica\Aggregation\DateRange;
use Elastica\Aggregation\ExtendedStats;
use Elastica\Aggregation\Filter as FilterAggregation;
use Elastica\Aggregation\Filters;
use Elastica\Aggregation\GeoDistance;
use Elastica\Aggregation\GeohashGrid;
use Elastica\Aggregation\GlobalAggregation;
Expand Down Expand Up @@ -233,10 +234,11 @@ public function filter($name, AbstractFilter $filter)
*
* @link http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/search-aggregations-bucket-filters-aggregation.html
* @param string $name
* @return Filters
*/
public function filters($name)
{
throw new NotImplementedException();
return new Filters($name);
}

/**
Expand Down
111 changes: 111 additions & 0 deletions test/lib/Elastica/Test/Aggregation/FiltersTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
<?php

namespace Elastica\Test\Aggregation;

use Elastica\Aggregation\Avg;
use Elastica\Aggregation\Filter;
use Elastica\Aggregation\Filters;
use Elastica\Document;
use Elastica\Filter\Range;
use Elastica\Filter\Term;
use Elastica\Query;

class FiltersTest extends BaseAggregationTest
{
protected function setUp()
{
parent::setUp();
$this->_index = $this->_createIndex("filter");
$docs = array(
new Document("1", array("price" => 5, "color" => "blue")),
new Document("2", array("price" => 8, "color" => "blue")),
new Document("3", array("price" => 1, "color" => "red")),
new Document("4", array("price" => 3, "color" => "green")),
);
$this->_index->getType("test")->addDocuments($docs);
$this->_index->refresh();
}

public function testToArrayUsingNamedFilters()
{
$expected = array(
"filters" => array(
"filters" => array(
"blue" => array(
"term" => array("color" => "blue")
),
"red" => array(
"term" => array("color" => "red")
)
)
),
"aggs" => array(
"avg_price" => array("avg" => array("field" => "price")),
),
);

$agg = new Filters("by_color");
$agg->addFilter(new Term(array('color' => 'blue')), 'blue');
$agg->addFilter(new Term(array('color' => 'red')), 'red');

$avg = new Avg("avg_price");
$avg->setField("price");
$agg->addAggregation($avg);

$this->assertEquals($expected, $agg->toArray());
}

public function testToArrayUsingAnonymousFilters()
{
$expected = array(
"filters" => array(
"filters" => array(
array(
"term" => array("color" => "blue")
),
array(
"term" => array("color" => "red")
)
)
),
"aggs" => array(
"avg_price" => array("avg" => array("field" => "price")),
),
);

$agg = new Filters("by_color");
$agg->addFilter(new Term(array("color" => "blue")));
$agg->addFilter(new Term(array("color" => "red")));

$avg = new Avg("avg_price");
$avg->setField("price");
$agg->addAggregation($avg);

$this->assertEquals($expected, $agg->toArray());
}

public function testFilterAggregation()
{
$agg = new Filters("by_color");
$agg->addFilter(new Term(array('color' => 'blue')), 'blue');
$agg->addFilter(new Term(array('color' => 'red')), 'red');

$avg = new Avg("avg_price");
$avg->setField("price");
$agg->addAggregation($avg);

$query = new Query();
$query->addAggregation($agg);

$results = $this->_index->search($query)->getAggregation("by_color");

$resultsForBlue = $results["buckets"]["blue"];
$resultsForRed = $results["buckets"]["red"];

$this->assertEquals(2, $resultsForBlue["doc_count"]);
$this->assertEquals(1, $resultsForRed["doc_count"]);

$this->assertEquals((5 + 8) / 2, $resultsForBlue["avg_price"]["value"]);
$this->assertEquals(1, $resultsForRed["avg_price"]["value"]);
}
}

0 comments on commit ac302eb

Please sign in to comment.