Skip to content

Commit

Permalink
range pivot (solariumphp#726)
Browse files Browse the repository at this point in the history
* range pivot

added the ability to add a pivot to your range facet
  • Loading branch information
wickedOne authored and Markus Kalkbrenner committed Jan 13, 2020
1 parent 120fe85 commit a28d911
Show file tree
Hide file tree
Showing 11 changed files with 249 additions and 21 deletions.
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/)
and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html).

## [unreleased]
### Added
- Range facet pivot support

### Fixed
- setting limit for pivot facets

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,19 +7,21 @@ The options below can be set as query option values, but also by using the set/g

Only the facet-type specific options are listed. See [Facetset component](V3:Facetset_component "wikilink") for the option shared by all facet types.

| Name | Type | Default value | Description |
|---------|--------|---------------|---------------------------------------------------------------------------------------------------------------------------------------------------------|
| field | string | null | This param indicates what field to create range facets for |
| start | string | null | The lower bound of the ranges. |
| end | string | null | The upper bound of the ranges. |
| gap | string | null | The size of each range expressed as a value to be added to the lower bound. |
| hardend | string | null | A Boolean parameter instructing Solr what to do in the event that facet.range.gap does not divide evenly between facet.range.start and facet.range.end. |
| other | string | null | This param indicates what to count in addition to the counts for each range constraint between facet.range.start and facet.range.en |
| include | string | null | Specify count bounds |
| Name | Type | Default value | Description |
|---------|----------------|---------------|---------------------------------------------------------------------------------------------------------------------------------------------------------|
| field | string | null | This param indicates what field to create range facets for |
| start | string | null | The lower bound of the ranges. |
| end | string | null | The upper bound of the ranges. |
| gap | string | null | The size of each range expressed as a value to be added to the lower bound. |
| hardend | string | null | A Boolean parameter instructing Solr what to do in the event that facet.range.gap does not divide evenly between facet.range.start and facet.range.end. |
| other | string | null | This param indicates what to count in addition to the counts for each range constraint between facet.range.start and facet.range.en |
| include | string | null | Specify count bounds |
| tag | string | null | When defined, it's used as the identifier in the select query. Required when specifying pivot fields |
| pivot | string / array | null | One or more fields which should be used to create pivot values |
||

Example
-------
Examples
--------

```php
<?php
Expand Down Expand Up @@ -69,3 +71,49 @@ foreach ($resultset as $document) {
htmlFooter();

```
or when specifying pivot fields:

```php
<?php

require(__DIR__.'/init.php');
htmlHeader();

// create a client instance
$client = new Solarium\Client($config);

// get a select query instance
$query = $client->createSelect();

// get the facetset component
$facetSet = $query->getFacetSet();

// create a facet field instance and set options
$facet = $facetSet->createFacetRange(['key' => 'manufacturedate_dt', 'tag' => 'r1']);

$facet->setField('manufacturedate_dt');
$facet->setStart('2006-01-01T00:00:00Z');
$facet->setEnd('NOW/YEAR'));
$facet->setGap('+1YEAR');
$facet->setPivot(['inStock']);

// this executes the query and returns the result
$resultset = $client->select($query);

// display the total number of documents found by solr
echo 'NumFound: '.$resultset->getNumFound();

// display pivot facet counts
echo '<hr/>Facet ranges:<br/>';
$facets = $resultset->getFacetSet()->getFacet('manufacturedate_dt');
foreach ($facets as $facet) {
foreach ($facet->getRanges() as $range) {
foreach ($range->getValues() as $date => $count) {
echo $date . ' [' . $count . ']<br/>';
}
}
}

htmlFooter();

```
18 changes: 18 additions & 0 deletions src/Component/Facet/AbstractRange.php
Original file line number Diff line number Diff line change
Expand Up @@ -260,6 +260,24 @@ public function getInclude(): array
return $include;
}

/**
* @param \Solarium\Component\Facet\Pivot|array $pivot
*
* @return \Solarium\Core\Configurable
*/
public function setPivot($pivot)
{
return $this->setOption('pivot', $pivot);
}

/**
* @return \Solarium\Component\Facet\Pivot|array|null
*/
public function getPivot()
{
return $this->getOption('pivot');
}

/**
* Initialize options.
*
Expand Down
2 changes: 2 additions & 0 deletions src/Component/Facet/Range.php
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,8 @@ protected function init()
case 'exclude':
$this->getLocalParameters()->addExcludes($value);
break;
case 'pivot':
$this->setPivot(new Pivot($value));
}
}
}
Expand Down
7 changes: 7 additions & 0 deletions src/Component/RequestBuilder/FacetSet.php
Original file line number Diff line number Diff line change
Expand Up @@ -218,6 +218,13 @@ public function addFacetRange($request, $facet)
foreach ($facet->getInclude() as $includeValue) {
$request->addParam("f.$field.facet.range.include", $includeValue);
}

if (null !== $pivot = $facet->getPivot()) {
$request->addParam(
'facet.pivot',
sprintf('%s%s', $pivot->getLocalParameters()->render(), implode(',', $pivot->getFields()))
);
}
}

/**
Expand Down
36 changes: 29 additions & 7 deletions src/Component/ResponseParser/FacetSet.php
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,6 @@ class FacetSet extends ResponseParserAbstract implements ComponentParserInterfac
/**
* Parse result data into result objects.
*
*
* @param ComponentAwareQueryInterface|AbstractQuery $query
* @param AbstractComponent|QueryFacetSet $facetSet
* @param array $data
Expand Down Expand Up @@ -148,15 +147,15 @@ protected function parseJsonFacetSet(array $facet_data, array $facets): array
{
$buckets_and_aggregations = [];
foreach ($facet_data as $key => $values) {
if (is_array($values)) {
if (\is_array($values)) {
if (isset($values['buckets'])) {
$buckets = [];
// Parse buckets.
foreach ($values['buckets'] as $bucket) {
$val = $bucket['val'];
$count = $bucket['count'];
unset($bucket['val']);
unset($bucket['count']);
unset($bucket['val'], $bucket['count']);

$buckets[] = new Bucket($val, $count, new ResultFacetSet($this->parseJsonFacetSet($bucket,
(isset($facets[$key]) && $facets[$key] instanceof JsonFacetInterface) ? $facets[$key]->getFacets() : []
)));
Expand All @@ -179,6 +178,7 @@ protected function parseJsonFacetSet(array $facet_data, array $facets): array
$buckets_and_aggregations[$key] = new Aggregation($values);
}
}

return $buckets_and_aggregations;
}

Expand Down Expand Up @@ -256,7 +256,7 @@ protected function facetMultiQuery(FacetInterface $facet, array $data): ?ResultF
}
}

if (count($values) <= 0) {
if (\count($values) <= 0) {
return null;
}

Expand All @@ -274,6 +274,28 @@ protected function facetMultiQuery(FacetInterface $facet, array $data): ?ResultF
*/
protected function facetRange(AbstractQuery $query, FacetInterface $facet, array $data): ?ResultFacetRange
{
if (null !== $pivot = $facet->getPivot()) {
foreach ($pivot->getLocalParameters()->getKeys() as $key) {
if (isset($data['facet_counts']['facet_pivot'][$key])) {
$pivot = $data['facet_counts']['facet_pivot'][$key];

foreach ($pivot as $pivotKey => $piv) {
if (isset($piv['ranges'])) {
foreach ($piv['ranges'] as $rangeKey => $range) {
if (isset($range['counts'])) {
$pivot[$pivotKey]['ranges'][$rangeKey]['counts'] = $this->convertToKeyValueArray($range['counts']);
}
}
}
}

$pivot = new ResultFacetPivot($pivot);
} else {
$pivot = null;
}
}
}

$key = $facet->getKey();
if (!isset($data['facet_counts']['facet_ranges'][$key])) {
return null;
Expand All @@ -291,7 +313,7 @@ protected function facetRange(AbstractQuery $query, FacetInterface $facet, array
$data['counts'] = $this->convertToKeyValueArray($data['counts']);
}

return new ResultFacetRange($data['counts'], $before, $after, $between, $start, $end, $gap);
return new ResultFacetRange($data['counts'], $before, $after, $between, $start, $end, $gap, $pivot);
}

/**
Expand Down Expand Up @@ -350,7 +372,7 @@ protected function pivotStats(PivotItem $pivotItem): void

if (null !== $stats = $pivotItem->getStats()) {
foreach ($stats->getResults() as $key => $result) {
if ($result instanceof Result || false === is_array($result)) {
if ($result instanceof Result || false === \is_array($result)) {
continue;
}

Expand Down
28 changes: 28 additions & 0 deletions src/Component/Result/Facet/Pivot/PivotItem.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
namespace Solarium\Component\Result\Facet\Pivot;

use Solarium\Component\Result\Stats\Stats;
use Solarium\Component\Result\Facet\Range;

/**
* Select field pivot result.
Expand Down Expand Up @@ -37,6 +38,11 @@ class PivotItem extends Pivot
*/
protected $stats;

/**
* @var \Solarium\Component\Result\Facet\Range[]
*/
protected $ranges;

/**
* Constructor.
*
Expand All @@ -59,6 +65,18 @@ public function __construct(array $data)
if (isset($data['stats'])) {
$this->stats = new Stats($data['stats']);
}

if (isset($data['ranges'])) {
foreach ($data['ranges'] as $range) {
$before = $range['before'] ?? null;
$after = $range['after'] ?? null;
$between = $range['between'] ?? null;
$start = $range['start'] ?? null;
$end = $range['end'] ?? null;
$gap = $range['gap'] ?? null;
$this->ranges[] = new Range($range['counts'], $before, $after, $between, $start, $end, $gap);
}
}
}

/**
Expand Down Expand Up @@ -100,4 +118,14 @@ public function getStats(): ?Stats
{
return $this->stats;
}

/**
* Get ranges.
*
* @return \Solarium\Component\Result\Facet\Range[]
*/
public function getRanges(): array
{
return $this->ranges;
}
}
20 changes: 19 additions & 1 deletion src/Component/Result/Facet/Range.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

namespace Solarium\Component\Result\Facet;

use Solarium\Component\Result\Facet\Pivot\Pivot;

/**
* Select range facet result.
*
Expand Down Expand Up @@ -56,6 +58,11 @@ class Range extends Field
*/
protected $gap;

/**
* @var \Solarium\Component\Result\Facet\Pivot\Pivot|null
*/
protected $pivot;

/**
* Constructor.
*
Expand All @@ -66,16 +73,19 @@ class Range extends Field
* @param string|int|null $start
* @param string|int|null $end
* @param string|int|null $gap
* @param Pivot|null $pivot
*/
public function __construct(array $values, ?int $before, ?int $after, ?int $between, $start, $end, $gap)
public function __construct(array $values, ?int $before, ?int $after, ?int $between, $start, $end, $gap, ?Pivot $pivot = null)
{
parent::__construct($values);

$this->before = $before;
$this->after = $after;
$this->between = $between;
$this->start = $start;
$this->end = $end;
$this->gap = $gap;
$this->pivot = $pivot;
}

/**
Expand Down Expand Up @@ -152,4 +162,12 @@ public function getGap(): string
{
return (string) $this->gap;
}

/**
* @return \Solarium\Component\Result\Facet\Pivot\Pivot|null
*/
public function getPivot(): ?Pivot
{
return $this->pivot;
}
}
25 changes: 25 additions & 0 deletions tests/Component/RequestBuilder/FacetSetTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -279,6 +279,31 @@ public function testBuildWithRangeFacetExcludingOptionalParams()
);
}

public function testBuildWithRangeFacetAndPivot()
{
$this->component->addFacet(
new FacetRange(
[
'key' => 'key',
'local_tag' => 'r1',
'field' => 'manufacturedate_dt',
'start' => '2006-01-01T00:00:00Z',
'end' => 'NOW/YEAR',
'gap' => '+1YEAR',
'pivot' => ['fields' => ['cat', 'inStock'], 'local_range' => 'r1'],
]
)
);

$request = $this->builder->buildComponent($this->component, $this->request);

$this->assertNull($request->getRawData());
$this->assertEquals(
'?facet.range={!key=key tag=r1}manufacturedate_dt&f.manufacturedate_dt.facet.range.start=2006-01-01T00:00:00Z&f.manufacturedate_dt.facet.range.end=NOW/YEAR&f.manufacturedate_dt.facet.range.gap=+1YEAR&facet.pivot={!range=r1}cat,inStock&facet=true',
urldecode($request->getUri())
);
}

public function testBuildWithFacetsAndGlobalFacetSettings()
{
$this->component->setMissing(true);
Expand Down
Loading

0 comments on commit a28d911

Please sign in to comment.