HasPostAggregations::postJavascript()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 9
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 7
CRAP Score 1

Importance

Changes 0
Metric Value
eloc 5
dl 0
loc 9
ccs 7
cts 7
cp 1
rs 10
c 0
b 0
f 0
cc 1
nc 1
nop 3
crap 1
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\JavaScriptPostAggregator;
22
use Level23\Druid\PostAggregations\ExpressionPostAggregator;
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(
195
        string $as,
196
        Closure|string $fieldOrClosure,
197
        ?array $splitPoints = null,
198
        ?int $numBins = null
199
    ): self {
200 3
        $fields = $this->buildFields([$fieldOrClosure]);
201 3
        if ($fields->count() != 1 || !$fields[0]) {
202 3
            throw new InvalidArgumentException('You can only provide one post-aggregation, field access or constant as input field');
203
        }
204
205 3
        $this->postAggregations[] = new HistogramPostAggregator(
206 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

206
            /** @scrutinizer ignore-type */ $fields[0],
Loading history...
207 3
            $as,
208 3
            $splitPoints,
209 3
            $numBins
210 3
        );
211
212 3
        return $this;
213
    }
214
215
    /**
216
     * This returns an approximation to the rank of a given value that is the fraction of the distribution less than
217
     * that value.
218
     *
219
     * To use this aggregator, make sure you include the extension in your druid server config file:
220
     *
221
     * druid.extensions.loadList=["druid-datasketches"]
222
     *
223
     * @param string         $as             The name which will be used in the output
224
     * @param Closure|string $fieldOrClosure Field which will be used that refers to a DoublesSketch  (fieldAccess or
225
     *                                       another post aggregator). When a string is given, we assume that it refers
226
     *                                       to another field in the query. If you give a closure, it will receive an
227
     *                                       instance of the PostAggregationsBuilder. With this builder you can build
228
     *                                       another post-aggregation or use constants as input for this method.
229
     * @param float|int      $value          This returns an approximation to the rank of a given value that is the
230
     *                                       fraction of the distribution less than that value.
231
     *
232
     * @return $this
233
     */
234 1
    public function rank(string $as, Closure|string $fieldOrClosure, float|int $value): self
235
    {
236 1
        $fields = $this->buildFields([$fieldOrClosure]);
237 1
        if ($fields->count() != 1 || !$fields[0]) {
238 1
            throw new InvalidArgumentException('You can only provide one post-aggregation, field access or constant as input field');
239
        }
240
241 1
        $this->postAggregations[] = new RankPostAggregator(
242 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

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

279
            /** @scrutinizer ignore-type */ $fields[0],
Loading history...
280 1
            $as,
281 1
            $splitPoints
282 1
        );
283
284 1
        return $this;
285
    }
286
287
    /**
288
     * This returns a summary of the sketch that can be used for debugging. This is the result of calling toString()
289
     * method.
290
     *
291
     * To use this aggregator, make sure you include the extension in your druid server config file:
292
     *
293
     * druid.extensions.loadList=["druid-datasketches"]
294
     *
295
     * @param string         $as             The name which will be used in the output
296
     * @param Closure|string $fieldOrClosure Field which will be used that refers to a DoublesSketch  (fieldAccess or
297
     *                                       another post aggregator). When a string is given, we assume that it refers
298
     *                                       to another field in the query. If you give a closure, it will receive an
299
     *                                       instance of the PostAggregationsBuilder. With this builder you can build
300
     *                                       another post-aggregation or use constants as input for this method.
301
     *
302
     * @return $this
303
     */
304 1
    public function sketchSummary(string $as, Closure|string $fieldOrClosure): self
305
    {
306 1
        $fields = $this->buildFields([$fieldOrClosure]);
307 1
        if ($fields->count() != 1 || !$fields[0]) {
308 1
            throw new InvalidArgumentException('You can only provide one post-aggregation, field access or constant as input field');
309
        }
310
311 1
        $this->postAggregations[] = new SketchSummaryPostAggregator(
312 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

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