Passed
Pull Request — master (#54)
by
unknown
15:30
created

HasPostAggregations::expression()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 8
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 4
c 1
b 0
f 0
dl 0
loc 8
ccs 0
cts 6
cp 0
rs 10
cc 1
nc 1
nop 2
crap 2
1
<?php
2
declare(strict_types=1);
3
4
namespace Level23\Druid\Concerns;
5
6
use Closure;
7
use InvalidArgumentException;
8
use Level23\Druid\Types\DataType;
9
use Level23\Druid\PostAggregations\CdfPostAggregator;
10
use Level23\Druid\PostAggregations\RankPostAggregator;
11
use Level23\Druid\PostAggregations\LeastPostAggregator;
12
use Level23\Druid\Collections\PostAggregationCollection;
13
use Level23\Druid\PostAggregations\ConstantPostAggregator;
14
use Level23\Druid\PostAggregations\GreatestPostAggregator;
15
use Level23\Druid\PostAggregations\QuantilePostAggregator;
16
use Level23\Druid\PostAggregations\PostAggregationsBuilder;
17
use Level23\Druid\PostAggregations\PostAggregatorInterface;
18
use Level23\Druid\PostAggregations\QuantilesPostAggregator;
19
use Level23\Druid\PostAggregations\HistogramPostAggregator;
20
use Level23\Druid\PostAggregations\ArithmeticPostAggregator;
21
use Level23\Druid\PostAggregations\ExpressionPostAggregator;
22
use Level23\Druid\PostAggregations\JavaScriptPostAggregator;
23
use Level23\Druid\PostAggregations\FieldAccessPostAggregator;
24
use Level23\Druid\PostAggregations\SketchSummaryPostAggregator;
25
use Level23\Druid\PostAggregations\HyperUniqueCardinalityPostAggregator;
26
27
trait HasPostAggregations
28
{
29
    /**
30
     * @var \Level23\Druid\PostAggregations\PostAggregatorInterface[]
31
     */
32
    protected array $postAggregations = [];
33
34
    /**
35
     * Build our input field for the post aggregation.
36
     * This array can contain:
37
     *  - A string, referring to a metric or dimension in the query
38
     *  - A Closure, which allows you to build another postAggregator
39
     *
40
     * @param array<string|Closure|PostAggregatorInterface|string[]> $fields
41
     *
42
     * @return PostAggregationCollection
43
     * @throws InvalidArgumentException
44
     */
45 26
    protected function buildFields(array $fields): PostAggregationCollection
46
    {
47 26
        $first = reset($fields);
48
49 26
        if (is_array($first)) {
50 16
            $fields = $first;
51
        }
52
53 26
        $collection = new PostAggregationCollection();
54
55 26
        foreach ($fields as $field) {
56 26
            if (is_string($field)) {
57 25
                $collection->add(new FieldAccessPostAggregator($field, $field));
58 10
            } elseif ($field instanceof PostAggregatorInterface) {
59 1
                $collection->add($field);
60 10
            } elseif ($field instanceof Closure) {
61 9
                $builder = new PostAggregationsBuilder();
62 9
                call_user_func($field, $builder);
63 9
                $postAggregations = $builder->getPostAggregations();
64
65 9
                $collection->add(...$postAggregations);
66
            } else {
67 1
                throw new InvalidArgumentException(
68 1
                    'Incorrect field type given in postAggregation fields. Only strings (which will become' .
69 1
                    'FieldAccess types), Objects of the type PostAggregatorInterface and Closure\'s are allowed!'
70 1
                );
71
            }
72
        }
73
74 25
        return $collection;
75
    }
76
77
    /**
78
     * Divide two or more fields with each other.
79
     *
80
     * @param string                  $as                The name which will be used in the output
81
     * @param string|Closure|string[] ...$fieldOrClosure One or more fields which will be used. When a string is given,
82
     *                                                   we assume that it refers to another field in the query. If you
83
     *                                                   give a closure, it will receive an instance of the
84
     *                                                   PostAggregationsBuilder. With this builder you can build other
85
     *                                                   post-aggregations or use constants as input for this method.
86
     *
87
     * @return $this
88
     */
89 7
    public function divide(string $as, ...$fieldOrClosure): self
90
    {
91 7
        $this->postAggregations[] = new ArithmeticPostAggregator(
92 7
            $as,
93 7
            '/',
94 7
            $this->buildFields($fieldOrClosure),
95 7
            true
96 7
        );
97
98 7
        return $this;
99
    }
100
101
    /**
102
     * This returns an approximation to the value that would be preceded by a given fraction of a hypothetical sorted
103
     * version of the input stream.
104
     *
105
     * To use this aggregator, make sure you include the extension in your druid server config file:
106
     *
107
     * druid.extensions.loadList=["druid-datasketches"]
108
     *
109
     * @param string         $as             The name which will be used in the output
110
     * @param Closure|string $fieldOrClosure Field which will be used that refers to a DoublesSketch  (fieldAccess or
111
     *                                       another post aggregator). When a string is given, we assume that it refers
112
     *                                       to another field in the query. If you give a closure, it will receive an
113
     *                                       instance of the PostAggregationsBuilder. With this builder you can build
114
     *                                       another post-aggregation or use constants as input for this method.
115
     * @param float          $fraction       Fractional position in the hypothetical sorted stream, number from 0 to 1
116
     *                                       inclusive
117
     *
118
     * @return $this
119
     */
120 1
    public function quantile(string $as, Closure|string $fieldOrClosure, float $fraction): self
121
    {
122 1
        $fields = $this->buildFields([$fieldOrClosure]);
123 1
        if ($fields->count() != 1 || !$fields[0]) {
124 1
            throw new InvalidArgumentException('You can only provide one post-aggregation, field access or constant as input field');
125
        }
126
127 1
        $this->postAggregations[] = new QuantilePostAggregator(
128 1
            $fields[0],
0 ignored issues
show
Bug introduced by
It seems like $fields[0] can also be of type null; however, parameter $dimension of Level23\Druid\PostAggreg...gregator::__construct() does only seem to accept Level23\Druid\PostAggreg...PostAggregatorInterface, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

128
            /** @scrutinizer ignore-type */ $fields[0],
Loading history...
129 1
            $as,
130 1
            $fraction
131 1
        );
132
133 1
        return $this;
134
    }
135
136
    /**
137
     * This returns an approximation to the value that would be preceded by a given fraction of a hypothetical sorted
138
     * version of the input stream. This returns an array of quantiles corresponding to a given array of fractions.
139
     *
140
     * To use this aggregator, make sure you include the extension in your druid server config file:
141
     *
142
     * druid.extensions.loadList=["druid-datasketches"]
143
     *
144
     * @param string         $as             The name which will be used in the output
145
     * @param Closure|string $fieldOrClosure Field which will be used that refers to a DoublesSketch  (fieldAccess or
146
     *                                       another post aggregator). When a string is given, we assume that it refers
147
     *                                       to another field in the query. If you give a closure, it will receive an
148
     *                                       instance of the PostAggregationsBuilder. With this builder you can build
149
     *                                       another post-aggregation or use constants as input for this method.
150
     * @param float[]        $fractions      Array of Fractional positions in the hypothetical sorted stream, number
151
     *                                       from 0 to 1 inclusive
152
     *
153
     * @return $this
154
     */
155 1
    public function quantiles(string $as, Closure|string $fieldOrClosure, array $fractions): self
156
    {
157 1
        $fields = $this->buildFields([$fieldOrClosure]);
158 1
        if ($fields->count() != 1 || !$fields[0]) {
159 1
            throw new InvalidArgumentException('You can only provide one post-aggregation, field access or constant as input field');
160
        }
161
162 1
        $this->postAggregations[] = new QuantilesPostAggregator(
163 1
            $fields[0],
0 ignored issues
show
Bug introduced by
It seems like $fields[0] can also be of type null; however, parameter $dimension of Level23\Druid\PostAggreg...gregator::__construct() does only seem to accept Level23\Druid\PostAggreg...PostAggregatorInterface, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

163
            /** @scrutinizer ignore-type */ $fields[0],
Loading history...
164 1
            $as,
165 1
            $fractions
166 1
        );
167
168 1
        return $this;
169
    }
170
171
    /**
172
     * This returns an approximation to the histogram given an array of split points that define the histogram bins or
173
     * a number of bins (not both). An array of m unique, monotonically increasing split points divide the real number
174
     * line into m+1 consecutive disjoint intervals. The definition of an interval is inclusive of the left split point
175
     * and exclusive of the right split point. If the number of bins is specified instead of split points, the interval
176
     * between the minimum and maximum values is divided into the given number of equally-spaced bins.
177
     *
178
     * To use this aggregator, make sure you include the extension in your druid server config file:
179
     *
180
     * druid.extensions.loadList=["druid-datasketches"]
181
     *
182
     * @param string                $as             The name which will be used in the output
183
     * @param Closure|string        $fieldOrClosure Field which will be used that refers to a DoublesSketch
184
     *                                              (fieldAccess or another post aggregator). When a string is given,
185
     *                                              we assume that it refers to another field in the query. If you give
186
     *                                              a closure, it will receive an instance of the
187
     *                                              PostAggregationsBuilder. With this builder you can build another
188
     *                                              post-aggregation or use constants as input for this method.
189
     * @param array<int|float>|null $splitPoints    Array of split points (optional)
190
     * @param int|null              $numBins        Number of bins (optional, defaults to 10)
191
     *
192
     * @return $this
193
     */
194 3
    public function histogram(string $as, Closure|string $fieldOrClosure, ?array $splitPoints = null, ?int $numBins = null): self
195
    {
196 3
        $fields = $this->buildFields([$fieldOrClosure]);
197 3
        if ($fields->count() != 1 || !$fields[0]) {
198 3
            throw new InvalidArgumentException('You can only provide one post-aggregation, field access or constant as input field');
199
        }
200
201 3
        $this->postAggregations[] = new HistogramPostAggregator(
202 3
            $fields[0],
0 ignored issues
show
Bug introduced by
It seems like $fields[0] can also be of type null; however, parameter $dimension of Level23\Druid\PostAggreg...gregator::__construct() does only seem to accept Level23\Druid\PostAggreg...PostAggregatorInterface, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

202
            /** @scrutinizer ignore-type */ $fields[0],
Loading history...
203 3
            $as,
204 3
            $splitPoints,
205 3
            $numBins
206 3
        );
207
208 3
        return $this;
209
    }
210
211
    /**
212
     * This returns an approximation to the rank of a given value that is the fraction of the distribution less than
213
     * that value.
214
     *
215
     * To use this aggregator, make sure you include the extension in your druid server config file:
216
     *
217
     * druid.extensions.loadList=["druid-datasketches"]
218
     *
219
     * @param string         $as             The name which will be used in the output
220
     * @param Closure|string $fieldOrClosure Field which will be used that refers to a DoublesSketch  (fieldAccess or
221
     *                                       another post aggregator). When a string is given, we assume that it refers
222
     *                                       to another field in the query. If you give a closure, it will receive an
223
     *                                       instance of the PostAggregationsBuilder. With this builder you can build
224
     *                                       another post-aggregation or use constants as input for this method.
225
     * @param float|int      $value          This returns an approximation to the rank of a given value that is the
226
     *                                       fraction of the distribution less than that value.
227
     *
228
     * @return $this
229
     */
230 1
    public function rank(string $as, Closure|string $fieldOrClosure, float|int $value): self
231
    {
232 1
        $fields = $this->buildFields([$fieldOrClosure]);
233 1
        if ($fields->count() != 1 || !$fields[0]) {
234 1
            throw new InvalidArgumentException('You can only provide one post-aggregation, field access or constant as input field');
235
        }
236
237 1
        $this->postAggregations[] = new RankPostAggregator(
238 1
            $fields[0],
0 ignored issues
show
Bug introduced by
It seems like $fields[0] can also be of type null; however, parameter $dimension of Level23\Druid\PostAggreg...gregator::__construct() does only seem to accept Level23\Druid\PostAggreg...PostAggregatorInterface, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

238
            /** @scrutinizer ignore-type */ $fields[0],
Loading history...
239 1
            $as,
240 1
            $value
241 1
        );
242
243 1
        return $this;
244
    }
245
246
    /**
247
     * This returns an approximation to the Cumulative Distribution Function given an array of split points that define
248
     * the edges of the bins. An array of m unique, monotonically increasing split points divide the real number line
249
     * into m+1 consecutive disjoint intervals. The definition of an interval is inclusive of the left split point and
250
     * exclusive of the right split point. The resulting array of fractions can be viewed as ranks of each split point
251
     * with one additional rank that is always 1.
252
     *
253
     * To use this aggregator, make sure you include the extension in your druid server config file:
254
     *
255
     * druid.extensions.loadList=["druid-datasketches"]
256
     *
257
     * @param string         $as             The name which will be used in the output
258
     * @param Closure|string $fieldOrClosure Field which will be used that refers to a DoublesSketch  (fieldAccess or
259
     *                                       another post aggregator). When a string is given, we assume that it refers
260
     *                                       to another field in the query. If you give a closure, it will receive an
261
     *                                       instance of the PostAggregationsBuilder. With this builder you can build
262
     *                                       another post-aggregation or use constants as input for this method.
263
     * @param float[]        $splitPoints    Array of split points
264
     *
265
     * @return $this
266
     */
267 1
    public function cdf(string $as, Closure|string $fieldOrClosure, array $splitPoints): self
268
    {
269 1
        $fields = $this->buildFields([$fieldOrClosure]);
270 1
        if ($fields->count() != 1 || !$fields[0]) {
271 1
            throw new InvalidArgumentException('You can only provide one post-aggregation, field access or constant as input field');
272
        }
273
274 1
        $this->postAggregations[] = new CdfPostAggregator(
275 1
            $fields[0],
0 ignored issues
show
Bug introduced by
It seems like $fields[0] can also be of type null; however, parameter $dimension of Level23\Druid\PostAggreg...gregator::__construct() does only seem to accept Level23\Druid\PostAggreg...PostAggregatorInterface, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

275
            /** @scrutinizer ignore-type */ $fields[0],
Loading history...
276 1
            $as,
277 1
            $splitPoints
278 1
        );
279
280 1
        return $this;
281
    }
282
283
    /**
284
     * This returns a summary of the sketch that can be used for debugging. This is the result of calling toString()
285
     * method.
286
     *
287
     * To use this aggregator, make sure you include the extension in your druid server config file:
288
     *
289
     * druid.extensions.loadList=["druid-datasketches"]
290
     *
291
     * @param string         $as             The name which will be used in the output
292
     * @param Closure|string $fieldOrClosure Field which will be used that refers to a DoublesSketch  (fieldAccess or
293
     *                                       another post aggregator). When a string is given, we assume that it refers
294
     *                                       to another field in the query. If you give a closure, it will receive an
295
     *                                       instance of the PostAggregationsBuilder. With this builder you can build
296
     *                                       another post-aggregation or use constants as input for this method.
297
     *
298
     * @return $this
299
     */
300 1
    public function sketchSummary(string $as, Closure|string $fieldOrClosure): self
301
    {
302 1
        $fields = $this->buildFields([$fieldOrClosure]);
303 1
        if ($fields->count() != 1 || !$fields[0]) {
304 1
            throw new InvalidArgumentException('You can only provide one post-aggregation, field access or constant as input field');
305
        }
306
307 1
        $this->postAggregations[] = new SketchSummaryPostAggregator(
308 1
            $fields[0],
0 ignored issues
show
Bug introduced by
It seems like $fields[0] can also be of type null; however, parameter $dimension of Level23\Druid\PostAggreg...gregator::__construct() does only seem to accept Level23\Druid\PostAggreg...PostAggregatorInterface, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

308
            /** @scrutinizer ignore-type */ $fields[0],
Loading history...
309 1
            $as
310 1
        );
311
312 1
        return $this;
313
    }
314
315
    /**
316
     * Multiply two or more fields with each other.
317
     *
318
     * @param string                  $as                The name which will be used in the output
319
     * @param string|Closure|string[] ...$fieldOrClosure One or more fields which will be used. When a string is given,
320
     *                                                   we assume that it refers to another field in the query. If you
321
     *                                                   give a closure, it will receive an instance of the
322
     *                                                   PostAggregationsBuilder. With this builder you can build other
323
     *                                                   post-aggregations or use constants as input for this method.
324
     *
325
     * @return $this
326
     */
327 1
    public function multiply(string $as, ...$fieldOrClosure): self
328
    {
329 1
        $this->postAggregations[] = new ArithmeticPostAggregator(
330 1
            $as,
331 1
            '*',
332 1
            $this->buildFields($fieldOrClosure),
333 1
            true
334 1
        );
335
336 1
        return $this;
337
    }
338
339
    /**
340
     * Subtract two or more fields with each other.
341
     *
342
     * @param string                  $as                The name which will be used in the output
343
     * @param string|Closure|string[] ...$fieldOrClosure One or more fields which will be used. When a string is given,
344
     *                                                   we assume that it refers to another field in the query. If you
345
     *                                                   give a closure, it will receive an instance of the
346
     *                                                   PostAggregationsBuilder. With this builder you can build other
347
     *                                                   post-aggregations or use constants as input for this method.
348
     *
349
     * @return $this
350
     */
351 1
    public function subtract(string $as, ...$fieldOrClosure): self
352
    {
353
354 1
        $this->postAggregations[] = new ArithmeticPostAggregator(
355 1
            $as,
356 1
            '-',
357 1
            $this->buildFields($fieldOrClosure),
358 1
            true
359 1
        );
360
361 1
        return $this;
362
    }
363
364
    /**
365
     * Add two or more fields with each other.
366
     *
367
     * @param string                  $as                The name which will be used in the output
368
     * @param string|Closure|string[] ...$fieldOrClosure One or more fields which will be used. When a string is given,
369
     *                                                   we assume that it refers to another field in the query. If you
370
     *                                                   give a closure, it will receive an instance of the
371
     *                                                   PostAggregationsBuilder. With this builder you can build other
372
     *                                                   post-aggregations or use constants as input for this method.
373
     *
374
     * @return $this
375
     */
376 1
    public function add(string $as, ...$fieldOrClosure): self
377
    {
378 1
        $this->postAggregations[] = new ArithmeticPostAggregator(
379 1
            $as,
380 1
            '+',
381 1
            $this->buildFields($fieldOrClosure),
382 1
            true
383 1
        );
384
385 1
        return $this;
386
    }
387
388
    /**
389
     * Return the quotient of two or more fields.
390
     *
391
     * @param string                  $as                The name which will be used in the output
392
     * @param string|Closure|string[] ...$fieldOrClosure One or more fields which will be used. When a string is given,
393
     *                                                   we assume that it refers to another field in the query. If you
394
     *                                                   give a closure, it will receive an instance of the
395
     *                                                   PostAggregationsBuilder. With this builder you can build other
396
     *                                                   post-aggregations or use constants as input for this method.
397
     *
398
     * @return $this
399
     */
400 1
    public function quotient(string $as, ...$fieldOrClosure): self
401
    {
402 1
        $this->postAggregations[] = new ArithmeticPostAggregator(
403 1
            $as,
404 1
            'quotient',
405 1
            $this->buildFields($fieldOrClosure),
406 1
            true
407 1
        );
408
409 1
        return $this;
410
    }
411
412
    /**
413
     * Field accessor post-aggregators
414
     *
415
     * These post-aggregators return the value produced by the specified aggregator.
416
     *
417
     * $aggregatorOutputName refers to the output name of the aggregator given in the aggregations portion of the
418
     * query. For complex aggregators, like "cardinality" and "hyperUnique", the type of the post-aggregator determines
419
     * what the post-aggregator will return.
420
     * Set $finalizing to `false`  to return the raw aggregation object, or use `true`
421
     * to return a finalized value, such as an estimated cardinality.
422
     *
423
     * @param string $aggregatorOutputName This refers to the output name of the aggregator given in the aggregations
424
     *                                     portion of the query
425
     * @param string $as                   The output name as how we can access it
426
     * @param bool   $finalizing           Set this to true if you want to return a finalized value, such as an
427
     *                                     estimated cardinality.
428
     *
429
     * @return $this
430
     */
431 11
    public function fieldAccess(string $aggregatorOutputName, string $as = '', bool $finalizing = false): self
432
    {
433 11
        $this->postAggregations[] = new FieldAccessPostAggregator(
434 11
            $aggregatorOutputName,
435 11
            ($as ?: $aggregatorOutputName),
436 11
            $finalizing
437 11
        );
438
439 11
        return $this;
440
    }
441
442
    /**
443
     * The constant post-aggregator always returns the specified value.
444
     *
445
     * @param float|int $numericValue This will be our static value
446
     * @param string    $as           The output name as how we can access it
447
     *
448
     * @return $this
449
     */
450 11
    public function constant(float|int $numericValue, string $as): self
451
    {
452 11
        $this->postAggregations[] = new ConstantPostAggregator($as, $numericValue);
453
454 11
        return $this;
455
    }
456
457
    /**
458
     * Return the highest value of multiple columns in one row.
459
     *
460
     * @param string                  $as                The name which will be used in the output
461
     * @param string|Closure|string[] ...$fieldOrClosure One or more fields which will be used. When a string is given,
462
     *                                                   we assume that it refers to another field in the query. If you
463
     *                                                   give a closure, it will receive an instance of the
464
     *                                                   PostAggregationsBuilder. With this builder you can build other
465
     *                                                   post-aggregations or use constants as input for this method.
466
     *
467
     * @return $this
468
     */
469 1
    public function longGreatest(string $as, ...$fieldOrClosure): self
470
    {
471 1
        $this->postAggregations[] = new GreatestPostAggregator(
472 1
            $as,
473 1
            $this->buildFields($fieldOrClosure),
474 1
            DataType::LONG
475 1
        );
476
477 1
        return $this;
478
    }
479
480
    /**
481
     * Return the highest value of multiple columns in one row.
482
     *
483
     * @param string                  $as                The name which will be used in the output
484
     * @param string|Closure|string[] ...$fieldOrClosure One or more fields which will be used. When a string is given,
485
     *                                                   we assume that it refers to another field in the query. If you
486
     *                                                   give a closure, it will receive an instance of the
487
     *                                                   PostAggregationsBuilder. With this builder you can build other
488
     *                                                   post-aggregations or use constants as input for this method.
489
     *
490
     * @return $this
491
     */
492 1
    public function doubleGreatest(string $as, ...$fieldOrClosure): self
493
    {
494 1
        $this->postAggregations[] = new GreatestPostAggregator(
495 1
            $as,
496 1
            $this->buildFields($fieldOrClosure),
497 1
            DataType::DOUBLE
498 1
        );
499
500 1
        return $this;
501
    }
502
503
    /**
504
     * Return the lowest value of multiple columns in one row.
505
     *
506
     * @param string                  $as                The name which will be used in the output
507
     * @param string|Closure|string[] ...$fieldOrClosure One or more fields which will be used. When a string is given,
508
     *                                                   we assume that it refers to another field in the query. If you
509
     *                                                   give a closure, it will receive an instance of the
510
     *                                                   PostAggregationsBuilder. With this builder you can build other
511
     *                                                   post-aggregations or use constants as input for this method.
512
     *
513
     * @return $this
514
     */
515 1
    public function longLeast(string $as, ...$fieldOrClosure): self
516
    {
517 1
        $this->postAggregations[] = new LeastPostAggregator(
518 1
            $as,
519 1
            $this->buildFields($fieldOrClosure),
520 1
            DataType::LONG
521 1
        );
522
523 1
        return $this;
524
    }
525
526
    /**
527
     * Return the lowest value of multiple columns in one row.
528
     *
529
     * @param string                  $as                The name which will be used in the output
530
     * @param string|Closure|string[] ...$fieldOrClosure One or more fields which will be used. When a string is given,
531
     *                                                   we assume that it refers to another field in the query. If you
532
     *                                                   give a closure, it will receive an instance of the
533
     *                                                   PostAggregationsBuilder. With this builder you can build other
534
     *                                                   post-aggregations or use constants as input for this method.
535
     *
536
     * @return $this
537
     */
538 1
    public function doubleLeast(string $as, ...$fieldOrClosure): self
539
    {
540 1
        $this->postAggregations[] = new LeastPostAggregator(
541 1
            $as,
542 1
            $this->buildFields($fieldOrClosure),
543 1
            DataType::DOUBLE
544 1
        );
545
546 1
        return $this;
547
    }
548
549
    /**
550
     * This Post Aggregation function applies the provided JavaScript function to the given fields. Fields are passed
551
     * as arguments to the JavaScript function in the given order.
552
     *
553
     * NOTE: JavaScript-based functionality is disabled by default. Please refer to the Druid JavaScript programming
554
     * guide for guidelines about using Druid's JavaScript functionality, including instructions on how to enable it.
555
     *
556
     * @param string                  $as                The output name
557
     * @param string                  $function          The javascript function which should be applied.
558
     * @param string|Closure|string[] ...$fieldOrClosure One or more fields which will be used. When a string is given,
559
     *                                                   we assume that it refers to another field in the query. If you
560
     *                                                   give a closure, it will receive an instance of the
561
     *                                                   PostAggregationsBuilder. With this builder you can build other
562
     *                                                   post-aggregations or use constants as input for this method.
563
     *
564
     * @return $this
565
     * @see https://druid.apache.org/docs/latest/querying/post-aggregations.html#javascript-post-aggregator
566
     */
567 1
    public function postJavascript(string $as, string $function, ...$fieldOrClosure): self
568
    {
569 1
        $this->postAggregations[] = new JavaScriptPostAggregator(
570 1
            $as,
571 1
            $this->buildFields($fieldOrClosure),
572 1
            $function
573 1
        );
574
575 1
        return $this;
576
    }
577
578
    /**
579
     * The hyperUniqueCardinality post aggregator is used to wrap a hyperUnique object such that it can be used in post
580
     * aggregations.
581
     *
582
     * This post-aggregator will inherit the rounding behavior of the aggregator it references. Note that this
583
     * inheritance is only effective if you directly reference an aggregator. Going through another post-aggregator,
584
     * for example, will cause the user-specified rounding behavior to get lost and default to "no rounding".
585
     *
586
     * @see https://druid.apache.org/docs/latest/querying/post-aggregations.html#hyperunique-cardinality-post-aggregator
587
     *
588
     * @param string      $hyperUniqueField The name field value of the hyperUnique aggregator
589
     * @param string|null $as               The output name
590
     *
591
     * @return $this
592
     */
593 1
    public function hyperUniqueCardinality(string $hyperUniqueField, string $as = null): self
594
    {
595 1
        $this->postAggregations[] = new HyperUniqueCardinalityPostAggregator($hyperUniqueField, $as);
596
597 1
        return $this;
598
    }
599
600
    /**
601
     * @return array|\Level23\Druid\PostAggregations\PostAggregatorInterface[]
602
     */
603 10
    public function getPostAggregations(): array
604
    {
605 10
        return $this->postAggregations;
606
    }
607
608
    public function expression(string $as, $expression): self
609
    {
610
        $this->postAggregations[] = new ExpressionPostAggregator(
611
            $as,
612
            $expression
613
        );
614
615
        return $this;
616
    }
617
}
618