Skip to content

Commit 6a77efa

Browse files
committed
New feature: Range aggregation via groupByRanges()
1 parent 11437b6 commit 6a77efa

6 files changed

Lines changed: 93 additions & 3 deletions

File tree

src/Eloquent/Docs/ModelDocs.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -168,6 +168,7 @@
168168
* @method static $this orderByDesc($column,$options = [])
169169
*-----------------------------------
170170
* @method static $this groupBy($groups)
171+
* @method static $this groupByRanges($column, array $ranges)
171172
*-----------------------------------
172173
* @method static $this orderByGeo($column, $pin, $direction = 'asc', $options = [])
173174
* @method static $this orderByGeoDesc($column, $pin, $options = [])

src/Query/Builder.php

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1917,6 +1917,17 @@ public function bucket($key, $type = null, $args = null, $aggregations = null):
19171917
return $this->bucketAggregation($key, $type, $args, $aggregations);
19181918
}
19191919

1920+
public function groupByRanges($column, $ranges = [])
1921+
{
1922+
$args = [
1923+
'field' => $column,
1924+
'ranges' => $ranges,
1925+
];
1926+
$key = $column.'_ranges';
1927+
1928+
return $this->bucketAggregation($key, 'range', $args);
1929+
}
1930+
19201931
/**
19211932
* Get the aggregations returned from query
19221933
*/

src/Query/Concerns/ProcessesBucketAggregations.php

Lines changed: 25 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,14 +17,18 @@ public function processBucketAggregations($bucketAggregations, $rawAggs): array
1717
protected function parseBucket($bucketAggregation, $rawAggs)
1818
{
1919
$key = $bucketAggregation['key'];
20+
$type = $bucketAggregation['type'] ?? null;
2021

2122
if (! isset($rawAggs[$key]['buckets'])) {
2223
return $rawAggs[$key];
2324
}
24-
25-
$result = collect($rawAggs[$key]['buckets'])->map(function ($bucket) use ($key) {
25+
$result = collect($rawAggs[$key]['buckets'])->map(function ($bucket) use ($key, $type) {
2626
$metricAggs = $this->appendMetricsToBucket($bucket);
27-
// ES is super annoying with how it does keys. For composite, it returns keys as an array but in other cases it does not.
27+
28+
if ($type === 'range') {
29+
return $this->makeRangeBucket($bucket, $metricAggs);
30+
}
31+
2832
if (! is_array($bucket['key'])) {
2933
$bucket['key'] = [$key => $bucket['key']];
3034
}
@@ -40,6 +44,24 @@ protected function parseBucket($bucketAggregation, $rawAggs)
4044
return $result->toArray();
4145
}
4246

47+
protected function makeRangeBucket($bucket, $metricAggs)
48+
{
49+
$cleanBucket = [
50+
'key' => $bucket['key'],
51+
'from' => $bucket['from'] ?? null,
52+
'to' => $bucket['to'] ?? null,
53+
];
54+
$docCount = $bucket['doc_count'] ?? 0;
55+
unset($bucket['doc_count']);
56+
$cleanBucket['count'] = $docCount;
57+
58+
return [
59+
...$cleanBucket,
60+
...$metricAggs,
61+
'_meta' => $this->metaFromResult(['doc_count' => $docCount]),
62+
];
63+
}
64+
4365
protected function appendMetricsToBucket($bucket)
4466
{
4567
if (! $this->query->metricsAggregations) {

src/Query/DSL/DslFactory.php

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22

33
namespace PDPhilip\Elasticsearch\Query\DSL;
44

5+
use PDPhilip\Elasticsearch\Utils\Helpers;
6+
57
class DslFactory
68
{
79
// ----------------------------------------------------------------------
@@ -493,6 +495,18 @@ public static function termsAggregation(string $field, int $size, array $options
493495
];
494496
}
495497

498+
public static function rangeAggregation(string $field, array $ranges)
499+
{
500+
$ranges = Helpers::sanitizeRanges($ranges);
501+
502+
return [
503+
'range' => [
504+
'field' => $field,
505+
'ranges' => $ranges,
506+
],
507+
];
508+
}
509+
496510
public static function filterTermsAggregationOptions(array $options): array
497511
{
498512
$allowedArgs = [

src/Query/Grammar.php

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1362,6 +1362,14 @@ protected function compileTermsAggregation(Builder $builder, array $aggregation)
13621362
return DslFactory::termsAggregation($indexableField, $builder->getLimit(), $options);
13631363
}
13641364

1365+
protected function compileRangeAggregation(Builder $builder, array $aggregation): array
1366+
{
1367+
$field = $aggregation['args']['field'];
1368+
$ranges = $aggregation['args']['ranges'];
1369+
1370+
return DslFactory::rangeAggregation($field, $ranges);
1371+
}
1372+
13651373
/**
13661374
* Apply inner hits options to the clause
13671375
*/

src/Utils/Helpers.php

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,4 +56,38 @@ public static function getLaravelCompatabilityVersion(): int
5656

5757
return $majorVersion;
5858
}
59+
60+
public static function sanitizeRanges($input)
61+
{
62+
$ranges = [];
63+
foreach ($input as $value) {
64+
$range = [];
65+
if (isset($value['from']) || isset($value['to'])) {
66+
if (! empty($value['from'])) {
67+
$range['from'] = $value['from'];
68+
}
69+
if (! empty($value['to'])) {
70+
$range['to'] = $value['to'];
71+
}
72+
73+
if (! empty($value['key'])) {
74+
$range['key'] = $value['key'];
75+
}
76+
$ranges[] = $range;
77+
78+
continue;
79+
}
80+
// assume its an array with values of from and to
81+
if ($value[0] !== null) {
82+
$range['from'] = $value[0];
83+
}
84+
if ($value[1] !== null) {
85+
$range['to'] = $value[1];
86+
}
87+
$ranges[] = $range;
88+
89+
}
90+
91+
return $ranges;
92+
}
5993
}

0 commit comments

Comments
 (0)