level23 /
druid-client
| 1 | <?php |
||
| 2 | declare(strict_types=1); |
||
| 3 | |||
| 4 | namespace Level23\Druid\Concerns; |
||
| 5 | |||
| 6 | use Closure; |
||
| 7 | use Level23\Druid\Types\DataType; |
||
| 8 | use Level23\Druid\Dimensions\Dimension; |
||
| 9 | use Level23\Druid\Queries\QueryBuilder; |
||
| 10 | use Level23\Druid\Filters\FilterBuilder; |
||
| 11 | use Level23\Druid\Filters\FilterInterface; |
||
| 12 | use Level23\Druid\Aggregations\MaxAggregator; |
||
| 13 | use Level23\Druid\Aggregations\MinAggregator; |
||
| 14 | use Level23\Druid\Aggregations\SumAggregator; |
||
| 15 | use Level23\Druid\Aggregations\AnyAggregator; |
||
| 16 | use Level23\Druid\Aggregations\LastAggregator; |
||
| 17 | use Level23\Druid\Dimensions\DimensionBuilder; |
||
| 18 | use Level23\Druid\Aggregations\CountAggregator; |
||
| 19 | use Level23\Druid\Aggregations\FirstAggregator; |
||
| 20 | use Level23\Druid\Aggregations\FilteredAggregator; |
||
| 21 | use Level23\Druid\Collections\DimensionCollection; |
||
| 22 | use Level23\Druid\Aggregations\AggregatorInterface; |
||
| 23 | use Level23\Druid\Aggregations\JavascriptAggregator; |
||
| 24 | use Level23\Druid\Aggregations\HyperUniqueAggregator; |
||
| 25 | use Level23\Druid\Aggregations\CardinalityAggregator; |
||
| 26 | use Level23\Druid\Aggregations\DoublesSketchAggregator; |
||
| 27 | use Level23\Druid\Aggregations\DistinctCountAggregator; |
||
| 28 | |||
| 29 | trait HasAggregations |
||
| 30 | { |
||
| 31 | protected ?QueryBuilder $query = null; |
||
| 32 | |||
| 33 | /** |
||
| 34 | * @var array|\Level23\Druid\Aggregations\AggregatorInterface[] |
||
| 35 | */ |
||
| 36 | protected array $aggregations = []; |
||
| 37 | |||
| 38 | /** |
||
| 39 | * @return array|\Level23\Druid\Aggregations\AggregatorInterface[] |
||
| 40 | */ |
||
| 41 | 1 | public function getAggregations(): array |
|
| 42 | { |
||
| 43 | 1 | return $this->aggregations; |
|
| 44 | } |
||
| 45 | |||
| 46 | /** |
||
| 47 | * Sum the given metric |
||
| 48 | * |
||
| 49 | * @param string $metric |
||
| 50 | * @param string $as |
||
| 51 | * @param string|DataType $type |
||
| 52 | * @param \Closure|null $filterBuilder A closure which receives a FilterBuilder. When given, we will only apply |
||
| 53 | * the "sum" function to the records which match with the given filter. |
||
| 54 | * |
||
| 55 | * @return $this |
||
| 56 | */ |
||
| 57 | 15 | public function sum( |
|
| 58 | string $metric, |
||
| 59 | string $as = '', |
||
| 60 | string|DataType $type = DataType::LONG, |
||
| 61 | ?Closure $filterBuilder = null |
||
| 62 | ): self { |
||
| 63 | 15 | $this->aggregations[] = $this->buildFilteredAggregation( |
|
| 64 | 15 | new SumAggregator($metric, $as, $type), |
|
| 65 | 15 | $filterBuilder |
|
| 66 | 15 | ); |
|
| 67 | |||
| 68 | 15 | return $this; |
|
| 69 | } |
||
| 70 | |||
| 71 | /** |
||
| 72 | * DoublesSketch is a mergeable streaming algorithm to estimate the distribution of values, and approximately |
||
| 73 | * answer queries about the rank of a value, probability mass function of the distribution (PMF) or histogram, |
||
| 74 | * cumulative distribution function (CDF), and quantiles (median, min, max, 95th percentile and such). See |
||
| 75 | * Quantiles Sketch Overview. |
||
| 76 | *s |
||
| 77 | * To make use of this aggregator you have to have the datasketches module enabled in your druid server: |
||
| 78 | * druid.extensions.loadList=["druid-datasketches"] |
||
| 79 | * |
||
| 80 | * |
||
| 81 | * @param string $metric A String for the name of the input field (can contain sketches or raw numeric |
||
| 82 | * values). |
||
| 83 | * @param string $as A String for the output (result) name of the calculation. |
||
| 84 | * @param int|null $sizeAndAccuracy Parameter that determines the accuracy and size of the sketch. Higher k means |
||
| 85 | * higher accuracy but more space to store sketches. Must be a power of 2 from 2 |
||
| 86 | * to 32768. See accuracy information in the DataSketches documentation for |
||
| 87 | * details. |
||
| 88 | * @param int|null $maxStreamLength This parameter is a temporary solution to avoid a known issue. It may be |
||
| 89 | * removed in a future release after the bug is fixed. This parameter defines the |
||
| 90 | * maximum number of items to store in each sketch. If a sketch reaches the limit, |
||
| 91 | * the query can throw IllegalStateException. To work around this issue, increase |
||
| 92 | * the maximum stream length. See accuracy information in the DataSketches |
||
| 93 | * documentation for how many bytes are required per stream length. |
||
| 94 | * |
||
| 95 | * @return $this |
||
| 96 | */ |
||
| 97 | 5 | public function doublesSketch( |
|
| 98 | string $metric, |
||
| 99 | string $as = '', |
||
| 100 | ?int $sizeAndAccuracy = null, |
||
| 101 | ?int $maxStreamLength = null |
||
| 102 | ): self { |
||
| 103 | 5 | $this->aggregations[] = new DoublesSketchAggregator( |
|
| 104 | 5 | $metric, |
|
| 105 | 5 | $as ?: $metric, |
|
| 106 | 5 | $sizeAndAccuracy, |
|
| 107 | 5 | $maxStreamLength |
|
| 108 | 5 | ); |
|
| 109 | |||
| 110 | 5 | return $this; |
|
| 111 | } |
||
| 112 | |||
| 113 | /** |
||
| 114 | * Shorthand for summing long's |
||
| 115 | * |
||
| 116 | * @param string $metric |
||
| 117 | * @param string $as |
||
| 118 | * @param \Closure|null $filterBuilder A closure which receives a FilterBuilder. When given, we will only apply |
||
| 119 | * the "sum" function to the records which match with the given filter. |
||
| 120 | * |
||
| 121 | * @return $this |
||
| 122 | */ |
||
| 123 | 7 | public function longSum(string $metric, string $as = '', ?Closure $filterBuilder = null): self |
|
| 124 | { |
||
| 125 | 7 | return $this->sum($metric, $as, DataType::LONG, $filterBuilder); |
|
| 126 | } |
||
| 127 | |||
| 128 | /** |
||
| 129 | * Shorthand for summing doubles |
||
| 130 | * |
||
| 131 | * @param string $metric |
||
| 132 | * @param string $as |
||
| 133 | * @param \Closure|null $filterBuilder A closure which receives a FilterBuilder. When given, we will only apply |
||
| 134 | * the "sum" function to the records which match with the given filter. |
||
| 135 | * |
||
| 136 | * @return $this |
||
| 137 | */ |
||
| 138 | 1 | public function doubleSum(string $metric, string $as = '', ?Closure $filterBuilder = null): self |
|
| 139 | { |
||
| 140 | 1 | return $this->sum($metric, $as, DataType::DOUBLE, $filterBuilder); |
|
| 141 | } |
||
| 142 | |||
| 143 | /** |
||
| 144 | * Shorthand for summing floats |
||
| 145 | * |
||
| 146 | * @param string $metric |
||
| 147 | * @param string $as |
||
| 148 | * @param \Closure|null $filterBuilder A closure which receives a FilterBuilder. When given, we will only apply |
||
| 149 | * the "sum" function to the records which match with the given filter. |
||
| 150 | * |
||
| 151 | * @return $this |
||
| 152 | */ |
||
| 153 | 1 | public function floatSum(string $metric, string $as = '', ?Closure $filterBuilder = null): self |
|
| 154 | { |
||
| 155 | 1 | return $this->sum($metric, $as, DataType::FLOAT, $filterBuilder); |
|
| 156 | } |
||
| 157 | |||
| 158 | /** |
||
| 159 | * Uses HyperLogLog to compute the estimated cardinality of a dimension that has been aggregated as a "hyperUnique" |
||
| 160 | * metric at indexing time. |
||
| 161 | * |
||
| 162 | * @see http://algo.inria.fr/flajolet/Publications/FlFuGaMe07.pdf |
||
| 163 | * |
||
| 164 | * @param string $metric |
||
| 165 | * @param string $as |
||
| 166 | * @param bool $round Only affects query-time behavior, and is ignored at ingestion-time. The |
||
| 167 | * HyperLogLog algorithm generates decimal estimates with some error. "round" can |
||
| 168 | * be set to true to round off estimated values to whole numbers. Note that even |
||
| 169 | * with rounding, the cardinality is still an estimate. |
||
| 170 | * @param bool $isInputHyperUnique Only affects ingestion-time behavior, and is ignored at query-time. Set to |
||
| 171 | * true to index pre-computed HLL (Base64 encoded output from druid-hll is |
||
| 172 | * expected). |
||
| 173 | * |
||
| 174 | * @return $this |
||
| 175 | */ |
||
| 176 | 5 | public function hyperUnique(string $metric, string $as, bool $round = false, bool $isInputHyperUnique = false): self |
|
| 177 | { |
||
| 178 | 5 | $this->aggregations[] = new HyperUniqueAggregator( |
|
| 179 | 5 | $as, $metric, $isInputHyperUnique, $round |
|
| 180 | 5 | ); |
|
| 181 | |||
| 182 | 5 | return $this; |
|
| 183 | } |
||
| 184 | |||
| 185 | /** |
||
| 186 | * Computes the cardinality of a set of Apache Druid (incubating) dimensions, using HyperLogLog to estimate the |
||
| 187 | * cardinality. Please note that this aggregator will be much slower than indexing a column with the hyperUnique |
||
| 188 | * aggregator. This aggregator also runs over a dimension column, which means the string dimension cannot be |
||
| 189 | * removed from the dataset to improve rollup. In general, we strongly recommend using the hyperUnique aggregator |
||
| 190 | * instead of the cardinality aggregator if you do not care about the individual values of a dimension. |
||
| 191 | * |
||
| 192 | * The HyperLogLog algorithm generates decimal estimates with some error. "round" can be set to true to round off |
||
| 193 | * estimated values to whole numbers. Note that even with rounding, the cardinality is still an estimate. The |
||
| 194 | * "round" field only affects query-time behavior, and is ignored at ingestion-time. |
||
| 195 | * |
||
| 196 | * When setting byRow to false (the default) it computes the cardinality of the set composed of the union of all |
||
| 197 | * dimension values for all the given dimensions. For a single dimension, this is equivalent to: |
||
| 198 | * ``` |
||
| 199 | * SELECT COUNT(DISTINCT(dimension)) FROM <datasource> |
||
| 200 | * ``` |
||
| 201 | * |
||
| 202 | * For multiple dimensions, this is equivalent to something akin to |
||
| 203 | * ``` |
||
| 204 | * SELECT COUNT(DISTINCT(value)) FROM ( |
||
| 205 | * SELECT dim_1 as value FROM <datasource> |
||
| 206 | * UNION |
||
| 207 | * SELECT dim_2 as value FROM <datasource> |
||
| 208 | * UNION |
||
| 209 | * SELECT dim_3 as value FROM <datasource> |
||
| 210 | * ) |
||
| 211 | * ``` |
||
| 212 | * |
||
| 213 | * When setting byRow to true it computes the cardinality by row, i.e. the cardinality of distinct dimension |
||
| 214 | * combinations. This is equivalent to something akin to |
||
| 215 | * |
||
| 216 | * ``` |
||
| 217 | * SELECT COUNT(*) FROM ( SELECT DIM1, DIM2, DIM3 FROM <datasource> GROUP BY DIM1, DIM2, DIM3 ) |
||
| 218 | * ``` |
||
| 219 | * |
||
| 220 | * @see https://druid.apache.org/docs/latest/querying/hll-old.html |
||
| 221 | * |
||
| 222 | * @param string $as The output name which is used for the result. |
||
| 223 | * @param \Closure|string[] $dimensionsOrDimensionBuilder An array with the dimensions which you want to calculate |
||
| 224 | * the cardinality over, or a closure which will receive a |
||
| 225 | * DimensionBuilder. You should build the dimensions which |
||
| 226 | * are used to calculate the cardinality over. |
||
| 227 | * @param bool $byRow For more details see method description. |
||
| 228 | * @param bool $round Only affects query-time behavior, and is ignored at |
||
| 229 | * ingestion-time. The HyperLogLog algorithm generates |
||
| 230 | * decimal estimates with some error. "round" can be set to |
||
| 231 | * true to round off estimated values to whole numbers. Note |
||
| 232 | * that even with rounding, the cardinality is still an |
||
| 233 | * estimate. |
||
| 234 | * |
||
| 235 | * @return $this |
||
| 236 | */ |
||
| 237 | 6 | public function cardinality( |
|
| 238 | string $as, |
||
| 239 | array|Closure $dimensionsOrDimensionBuilder, |
||
| 240 | bool $byRow = false, |
||
| 241 | bool $round = false |
||
| 242 | ): self { |
||
| 243 | 6 | if ($dimensionsOrDimensionBuilder instanceof Closure) { |
|
|
0 ignored issues
–
show
introduced
by
Loading history...
|
|||
| 244 | 5 | $builder = new DimensionBuilder(); |
|
| 245 | 5 | call_user_func($dimensionsOrDimensionBuilder, $builder); |
|
| 246 | 5 | $dimensions = $builder->getDimensions(); |
|
| 247 | } else { |
||
| 248 | 1 | $dimensions = []; |
|
| 249 | |||
| 250 | 1 | foreach ($dimensionsOrDimensionBuilder as $dimension) { |
|
| 251 | 1 | $dimensions[] = new Dimension($dimension); |
|
| 252 | } |
||
| 253 | } |
||
| 254 | |||
| 255 | 6 | $this->aggregations[] = new CardinalityAggregator( |
|
| 256 | 6 | $as, |
|
| 257 | 6 | new DimensionCollection(...$dimensions), |
|
| 258 | 6 | $byRow, |
|
| 259 | 6 | $round |
|
| 260 | 6 | ); |
|
| 261 | |||
| 262 | 6 | return $this; |
|
| 263 | } |
||
| 264 | |||
| 265 | /** |
||
| 266 | * When a closure is given, we will call the given function which is responsible for building a filter. |
||
| 267 | * We will then only apply the given aggregator for the records where the filter matches. |
||
| 268 | * |
||
| 269 | * @param \Level23\Druid\Aggregations\AggregatorInterface $aggregator |
||
| 270 | * @param \Closure|null $filterBuilder |
||
| 271 | * |
||
| 272 | * @return \Level23\Druid\Aggregations\AggregatorInterface |
||
| 273 | */ |
||
| 274 | 16 | protected function buildFilteredAggregation( |
|
| 275 | AggregatorInterface $aggregator, |
||
| 276 | ?Closure $filterBuilder = null |
||
| 277 | ): AggregatorInterface { |
||
| 278 | 16 | if (!$filterBuilder) { |
|
| 279 | 13 | return $aggregator; |
|
| 280 | } |
||
| 281 | |||
| 282 | 3 | $builder = new FilterBuilder($this->query); |
|
| 283 | 3 | call_user_func($filterBuilder, $builder); |
|
| 284 | 3 | $filter = $builder->getFilter(); |
|
| 285 | |||
| 286 | 3 | if ($filter instanceof FilterInterface) { |
|
| 287 | 2 | return new FilteredAggregator($filter, $aggregator); |
|
| 288 | } |
||
| 289 | |||
| 290 | 1 | return $aggregator; |
|
| 291 | } |
||
| 292 | |||
| 293 | /** |
||
| 294 | * Count the number of results and put it in a dimension with the given name. |
||
| 295 | * |
||
| 296 | * @param string $as |
||
| 297 | * @param \Closure|null $filterBuilder A closure which receives a FilterBuilder. When given, we will only count the |
||
| 298 | * records which match with the given filter. |
||
| 299 | * |
||
| 300 | * @return $this |
||
| 301 | */ |
||
| 302 | 1 | public function count(string $as, ?Closure $filterBuilder = null): self |
|
| 303 | { |
||
| 304 | 1 | $this->aggregations[] = $this->buildFilteredAggregation( |
|
| 305 | 1 | new CountAggregator($as), |
|
| 306 | 1 | $filterBuilder |
|
| 307 | 1 | ); |
|
| 308 | |||
| 309 | 1 | return $this; |
|
| 310 | } |
||
| 311 | |||
| 312 | /** |
||
| 313 | * Count the number of distinct values of a specific dimension. |
||
| 314 | * NOTE: The DataSketches Theta Sketch extension is required to run this aggregation. |
||
| 315 | * |
||
| 316 | * @param string $dimension |
||
| 317 | * @param string $as |
||
| 318 | * @param int $size Must be a power of 2. Internally, size refers to the maximum number of |
||
| 319 | * entries sketch object will retain. Higher size means higher accuracy but |
||
| 320 | * more space to store sketches. Note that after you index with a particular |
||
| 321 | * size, druid will persist sketch in segments, and you will use size greater or |
||
| 322 | * equal to that at query time. See the DataSketches site for details. In |
||
| 323 | * general, We recommend just sticking to default size. |
||
| 324 | * @param \Closure|null $filterBuilder A closure which receives a FilterBuilder. When given, we will only count the |
||
| 325 | * records which match with the given filter. |
||
| 326 | * |
||
| 327 | * @return $this |
||
| 328 | */ |
||
| 329 | 2 | public function distinctCount( |
|
| 330 | string $dimension, |
||
| 331 | string $as = '', |
||
| 332 | int $size = 16384, |
||
| 333 | ?Closure $filterBuilder = null |
||
| 334 | ): self { |
||
| 335 | 2 | $this->aggregations[] = $this->buildFilteredAggregation( |
|
| 336 | 2 | new DistinctCountAggregator($dimension, ($as ?: $dimension), $size), |
|
| 337 | 2 | $filterBuilder |
|
| 338 | 2 | ); |
|
| 339 | |||
| 340 | 2 | return $this; |
|
| 341 | } |
||
| 342 | |||
| 343 | /** |
||
| 344 | * Get the minimum value for the given metric |
||
| 345 | * |
||
| 346 | * @param string $metric |
||
| 347 | * @param string $as |
||
| 348 | * @param string|DataType $type |
||
| 349 | * @param \Closure|null $filterBuilder A closure which receives a FilterBuilder. When given, we will only apply the |
||
| 350 | * min function to the records which match with the given filter. |
||
| 351 | * |
||
| 352 | * @return $this |
||
| 353 | */ |
||
| 354 | 2 | public function min( |
|
| 355 | string $metric, |
||
| 356 | string $as = '', |
||
| 357 | string|DataType $type = DataType::LONG, |
||
| 358 | ?Closure $filterBuilder = null |
||
| 359 | ): self { |
||
| 360 | 2 | $this->aggregations[] = $this->buildFilteredAggregation( |
|
| 361 | 2 | new MinAggregator($metric, $as, $type), |
|
| 362 | 2 | $filterBuilder |
|
| 363 | 2 | ); |
|
| 364 | |||
| 365 | 2 | return $this; |
|
| 366 | } |
||
| 367 | |||
| 368 | /** |
||
| 369 | * Get the minimum value for the given metric using long as type |
||
| 370 | * |
||
| 371 | * @param string $metric |
||
| 372 | * @param string $as |
||
| 373 | * @param \Closure|null $filterBuilder A closure which receives a FilterBuilder. When given, we will only apply the |
||
| 374 | * min function to the records which match with the given filter. |
||
| 375 | * |
||
| 376 | * @return $this |
||
| 377 | */ |
||
| 378 | 1 | public function longMin(string $metric, string $as = '', ?Closure $filterBuilder = null): self |
|
| 379 | { |
||
| 380 | 1 | return $this->min($metric, $as, DataType::LONG, $filterBuilder); |
|
| 381 | } |
||
| 382 | |||
| 383 | /** |
||
| 384 | * Get the minimum value for the given metric using double as type |
||
| 385 | * |
||
| 386 | * @param string $metric |
||
| 387 | * @param string $as |
||
| 388 | * @param \Closure|null $filterBuilder A closure which receives a FilterBuilder. When given, we will only apply the |
||
| 389 | * min function to the records which match with the given filter. |
||
| 390 | * |
||
| 391 | * @return $this |
||
| 392 | */ |
||
| 393 | 1 | public function doubleMin(string $metric, string $as = '', ?Closure $filterBuilder = null): self |
|
| 394 | { |
||
| 395 | 1 | return $this->min($metric, $as, DataType::DOUBLE, $filterBuilder); |
|
| 396 | } |
||
| 397 | |||
| 398 | /** |
||
| 399 | * Get the minimum value for the given metric using float as type |
||
| 400 | * |
||
| 401 | * @param string $metric |
||
| 402 | * @param string $as |
||
| 403 | * @param \Closure|null $filterBuilder A closure which receives a FilterBuilder. When given, we will only apply the |
||
| 404 | * min function to the records which match with the given filter. |
||
| 405 | * |
||
| 406 | * @return $this |
||
| 407 | */ |
||
| 408 | 1 | public function floatMin(string $metric, string $as = '', ?Closure $filterBuilder = null): self |
|
| 409 | { |
||
| 410 | 1 | return $this->min($metric, $as, DataType::FLOAT, $filterBuilder); |
|
| 411 | } |
||
| 412 | |||
| 413 | /** |
||
| 414 | * Get the maximum value for the given metric |
||
| 415 | * |
||
| 416 | * @param string $metric |
||
| 417 | * @param string $as |
||
| 418 | * @param string|DataType $type |
||
| 419 | * @param \Closure|null $filterBuilder A closure which receives a FilterBuilder. When given, we will only apply the |
||
| 420 | * max function to the records which match with the given filter. |
||
| 421 | * |
||
| 422 | * @return $this |
||
| 423 | */ |
||
| 424 | 2 | public function max( |
|
| 425 | string $metric, |
||
| 426 | string $as = '', |
||
| 427 | string|DataType $type = DataType::LONG, |
||
| 428 | ?Closure $filterBuilder = null |
||
| 429 | ): self { |
||
| 430 | 2 | $this->aggregations[] = $this->buildFilteredAggregation( |
|
| 431 | 2 | new MaxAggregator($metric, $as, $type), |
|
| 432 | 2 | $filterBuilder |
|
| 433 | 2 | ); |
|
| 434 | |||
| 435 | 2 | return $this; |
|
| 436 | } |
||
| 437 | |||
| 438 | /** |
||
| 439 | * Get the maximum value for the given metric using long as type |
||
| 440 | * |
||
| 441 | * @param string $metric |
||
| 442 | * @param string $as |
||
| 443 | * @param \Closure|null $filterBuilder A closure which receives a FilterBuilder. When given, we will only apply the |
||
| 444 | * max function to the records which match with the given filter. |
||
| 445 | * |
||
| 446 | * @return $this |
||
| 447 | */ |
||
| 448 | 1 | public function longMax(string $metric, string $as = '', ?Closure $filterBuilder = null): self |
|
| 449 | { |
||
| 450 | 1 | return $this->max($metric, $as, DataType::LONG, $filterBuilder); |
|
| 451 | } |
||
| 452 | |||
| 453 | /** |
||
| 454 | * Get the maximum value for the given metric using float as type |
||
| 455 | * |
||
| 456 | * @param string $metric |
||
| 457 | * @param string $as |
||
| 458 | * @param \Closure|null $filterBuilder A closure which receives a FilterBuilder. When given, we will only apply the |
||
| 459 | * max function to the records which match with the given filter. |
||
| 460 | * |
||
| 461 | * @return $this |
||
| 462 | */ |
||
| 463 | 1 | public function floatMax(string $metric, string $as = '', ?Closure $filterBuilder = null): self |
|
| 464 | { |
||
| 465 | 1 | return $this->max($metric, $as, DataType::FLOAT, $filterBuilder); |
|
| 466 | } |
||
| 467 | |||
| 468 | /** |
||
| 469 | * Get the maximum value for the given metric using double as type |
||
| 470 | * |
||
| 471 | * @param string $metric |
||
| 472 | * @param string $as |
||
| 473 | * @param \Closure|null $filterBuilder A closure which receives a FilterBuilder. When given, we will only apply the |
||
| 474 | * max function to the records which match with the given filter. |
||
| 475 | * |
||
| 476 | * @return $this |
||
| 477 | */ |
||
| 478 | 1 | public function doubleMax(string $metric, string $as = '', ?Closure $filterBuilder = null): self |
|
| 479 | { |
||
| 480 | 1 | return $this->max($metric, $as, DataType::DOUBLE, $filterBuilder); |
|
| 481 | } |
||
| 482 | |||
| 483 | /** |
||
| 484 | * Get the any-metric found based on the applied group-by filters. |
||
| 485 | * Returns any value including null. This aggregator can simplify and |
||
| 486 | * optimize the performance by returning the first encountered value (including null) |
||
| 487 | * |
||
| 488 | * ANY aggregator cannot be used in ingestion spec, and should only be specified as part of queries. |
||
| 489 | * |
||
| 490 | * @param string $metric |
||
| 491 | * @param string $as |
||
| 492 | * @param string|DataType $type |
||
| 493 | * @param int|null $maxStringBytes For string types only. Optional, defaults to 1024. |
||
| 494 | * @param \Closure|null $filterBuilder A closure which receives a FilterBuilder. When given, we will only apply the |
||
| 495 | * "any" function to the records which match with the given filter. |
||
| 496 | * |
||
| 497 | * @return $this |
||
| 498 | */ |
||
| 499 | 2 | public function any( |
|
| 500 | string $metric, |
||
| 501 | string $as = '', |
||
| 502 | string|DataType $type = DataType::LONG, |
||
| 503 | ?int $maxStringBytes = null, |
||
| 504 | ?Closure $filterBuilder = null |
||
| 505 | ): self { |
||
| 506 | 2 | $this->aggregations[] = $this->buildFilteredAggregation( |
|
| 507 | 2 | new AnyAggregator($metric, $as, $type, $maxStringBytes), |
|
| 508 | 2 | $filterBuilder |
|
| 509 | 2 | ); |
|
| 510 | |||
| 511 | 2 | return $this; |
|
| 512 | } |
||
| 513 | |||
| 514 | /** |
||
| 515 | * Get the any-metric found based on the applied group-by filters. |
||
| 516 | * Returns any value including null. This aggregator can simplify and |
||
| 517 | * optimize the performance by returning the first encountered value (including null) |
||
| 518 | * |
||
| 519 | * ANY aggregator cannot be used in ingestion spec, and should only be specified as part of queries. |
||
| 520 | * |
||
| 521 | * @param string $metric |
||
| 522 | * @param string $as |
||
| 523 | * @param \Closure|null $filterBuilder A closure which receives a FilterBuilder. When given, we will only apply the |
||
| 524 | * "any" function to the records which match with the given filter. |
||
| 525 | * |
||
| 526 | * @return $this |
||
| 527 | */ |
||
| 528 | 1 | public function doubleAny(string $metric, string $as = '', ?Closure $filterBuilder = null): self |
|
| 529 | { |
||
| 530 | 1 | return $this->any($metric, $as, DataType::DOUBLE, null, $filterBuilder); |
|
| 531 | } |
||
| 532 | |||
| 533 | /** |
||
| 534 | * Get the any-metric found based on the applied group-by filters. |
||
| 535 | * Returns any value including null. This aggregator can simplify and |
||
| 536 | * optimize the performance by returning the first encountered value (including null) |
||
| 537 | * |
||
| 538 | * ANY aggregator cannot be used in ingestion spec, and should only be specified as part of queries. |
||
| 539 | * |
||
| 540 | * @param string $metric |
||
| 541 | * @param string $as |
||
| 542 | * @param \Closure|null $filterBuilder A closure which receives a FilterBuilder. When given, we will only apply the |
||
| 543 | * "any" function to the records which match with the given filter. |
||
| 544 | * |
||
| 545 | * @return $this |
||
| 546 | */ |
||
| 547 | 1 | public function floatAny(string $metric, string $as = '', ?Closure $filterBuilder = null): self |
|
| 548 | { |
||
| 549 | 1 | return $this->any($metric, $as, DataType::FLOAT, null, $filterBuilder); |
|
| 550 | } |
||
| 551 | |||
| 552 | /** |
||
| 553 | * Get the any-metric found based on the applied group-by filters. |
||
| 554 | * Returns any value including null. This aggregator can simplify and |
||
| 555 | * optimize the performance by returning the first encountered value (including null) |
||
| 556 | * |
||
| 557 | * ANY aggregator cannot be used in ingestion spec, and should only be specified as part of queries. |
||
| 558 | * |
||
| 559 | * @param string $metric |
||
| 560 | * @param string $as |
||
| 561 | * @param \Closure|null $filterBuilder A closure which receives a FilterBuilder. When given, we will only apply the |
||
| 562 | * "any" function to the records which match with the given filter. |
||
| 563 | * |
||
| 564 | * @return $this |
||
| 565 | */ |
||
| 566 | 1 | public function longAny(string $metric, string $as = '', ?Closure $filterBuilder = null): self |
|
| 567 | { |
||
| 568 | 1 | return $this->any($metric, $as, DataType::LONG, null, $filterBuilder); |
|
| 569 | } |
||
| 570 | |||
| 571 | /** |
||
| 572 | * Get the any-metric found based on the applied group-by filters. |
||
| 573 | * Returns any value including null. This aggregator can simplify and |
||
| 574 | * optimize the performance by returning the first encountered value (including null) |
||
| 575 | * |
||
| 576 | * ANY aggregator cannot be used in ingestion spec, and should only be specified as part of queries. |
||
| 577 | * |
||
| 578 | * @param string $metric |
||
| 579 | * @param string $as |
||
| 580 | * @param int|null $maxStringBytes Optional, defaults to 1024 |
||
| 581 | * @param \Closure|null $filterBuilder A closure which receives a FilterBuilder. When given, we will only apply the |
||
| 582 | * "any" function to the records which match with the given filter. |
||
| 583 | * |
||
| 584 | * @return $this |
||
| 585 | */ |
||
| 586 | 1 | public function stringAny( |
|
| 587 | string $metric, |
||
| 588 | string $as = '', |
||
| 589 | ?int $maxStringBytes = null, |
||
| 590 | ?Closure $filterBuilder = null |
||
| 591 | ): self { |
||
| 592 | 1 | return $this->any($metric, $as, DataType::STRING, $maxStringBytes, $filterBuilder); |
|
| 593 | } |
||
| 594 | |||
| 595 | /** |
||
| 596 | * Get the first metric found based on the applied group-by filters. |
||
| 597 | * So if you group by the dimension "countries", you can get the first "metric" per country. |
||
| 598 | * |
||
| 599 | * NOTE: This is different from the Laravel ELOQUENT first() method! |
||
| 600 | * |
||
| 601 | * @param string $metric |
||
| 602 | * @param string $as |
||
| 603 | * @param string|DataType $type |
||
| 604 | * @param \Closure|null $filterBuilder A closure which receives a FilterBuilder. When given, we will only apply the |
||
| 605 | * "first" function to the records which match with the given filter. |
||
| 606 | * |
||
| 607 | * @return $this |
||
| 608 | */ |
||
| 609 | 3 | public function first( |
|
| 610 | string $metric, |
||
| 611 | string $as = '', |
||
| 612 | string|DataType $type = DataType::LONG, |
||
| 613 | ?Closure $filterBuilder = null |
||
| 614 | ): self { |
||
| 615 | 3 | $this->aggregations[] = $this->buildFilteredAggregation( |
|
| 616 | 3 | new FirstAggregator($metric, $as, $type), |
|
| 617 | 3 | $filterBuilder |
|
| 618 | 3 | ); |
|
| 619 | |||
| 620 | 3 | return $this; |
|
| 621 | } |
||
| 622 | |||
| 623 | /** |
||
| 624 | * Get the first metric found based on the applied group-by filters. |
||
| 625 | * So if you group by the dimension "countries", you can get the first "metric" per country. |
||
| 626 | * |
||
| 627 | * NOTE: This is different from the Laravel ELOQUENT first() method! |
||
| 628 | * |
||
| 629 | * @param string $metric |
||
| 630 | * @param string $as |
||
| 631 | * @param \Closure|null $filterBuilder A closure which receives a FilterBuilder. When given, we will only apply the |
||
| 632 | * "first" function to the records which match with the given filter. |
||
| 633 | * |
||
| 634 | * @return $this |
||
| 635 | */ |
||
| 636 | 1 | public function longFirst(string $metric, string $as = '', ?Closure $filterBuilder = null): self |
|
| 637 | { |
||
| 638 | 1 | return $this->first($metric, $as, DataType::LONG, $filterBuilder); |
|
| 639 | } |
||
| 640 | |||
| 641 | /** |
||
| 642 | * Get the first metric found based on the applied group-by filters. |
||
| 643 | * So if you group by the dimension "countries", you can get the first "metric" per country. |
||
| 644 | * |
||
| 645 | * NOTE: This is different from the Laravel ELOQUENT first() method! |
||
| 646 | * |
||
| 647 | * @param string $metric |
||
| 648 | * @param string $as |
||
| 649 | * @param \Closure|null $filterBuilder A closure which receives a FilterBuilder. When given, we will only apply the |
||
| 650 | * "first" function to the records which match with the given filter. |
||
| 651 | * |
||
| 652 | * @return $this |
||
| 653 | */ |
||
| 654 | 1 | public function floatFirst(string $metric, string $as = '', ?Closure $filterBuilder = null): self |
|
| 655 | { |
||
| 656 | 1 | return $this->first($metric, $as, DataType::FLOAT, $filterBuilder); |
|
| 657 | } |
||
| 658 | |||
| 659 | /** |
||
| 660 | * Get the first metric found based on the applied group-by filters. |
||
| 661 | * So if you group by the dimension "countries", you can get the first "metric" per country. |
||
| 662 | * |
||
| 663 | * NOTE: This is different from the Laravel ELOQUENT first() method! |
||
| 664 | * |
||
| 665 | * @param string $metric |
||
| 666 | * @param string $as |
||
| 667 | * @param \Closure|null $filterBuilder A closure which receives a FilterBuilder. When given, we will only apply the |
||
| 668 | * "first" function to the records which match with the given filter. |
||
| 669 | * |
||
| 670 | * @return $this |
||
| 671 | */ |
||
| 672 | 1 | public function doubleFirst(string $metric, string $as = '', ?Closure $filterBuilder = null): self |
|
| 673 | { |
||
| 674 | 1 | return $this->first($metric, $as, DataType::DOUBLE, $filterBuilder); |
|
| 675 | } |
||
| 676 | |||
| 677 | /** |
||
| 678 | * Get the first metric found based on the applied group-by filters. |
||
| 679 | * So if you group by the dimension "countries", you can get the first "metric" per country. |
||
| 680 | * |
||
| 681 | * NOTE: This is different from the Laravel ELOQUENT first() method! |
||
| 682 | * |
||
| 683 | * @param string $metric |
||
| 684 | * @param string $as |
||
| 685 | * @param \Closure|null $filterBuilder A closure which receives a FilterBuilder. When given, we will only apply the |
||
| 686 | * "first" function to the records which match with the given filter. |
||
| 687 | * |
||
| 688 | * @return $this |
||
| 689 | */ |
||
| 690 | 1 | public function stringFirst(string $metric, string $as = '', ?Closure $filterBuilder = null): self |
|
| 691 | { |
||
| 692 | 1 | return $this->first($metric, $as, DataType::STRING, $filterBuilder); |
|
| 693 | } |
||
| 694 | |||
| 695 | /** |
||
| 696 | * Get the last metric found |
||
| 697 | * |
||
| 698 | * @param string $metric |
||
| 699 | * @param string $as |
||
| 700 | * @param string|DataType $type |
||
| 701 | * @param \Closure|null $filterBuilder A closure which receives a FilterBuilder. When given, we will only apply the |
||
| 702 | * "last" function to the records which match with the given filter. |
||
| 703 | * |
||
| 704 | * @return $this |
||
| 705 | */ |
||
| 706 | 2 | public function last( |
|
| 707 | string $metric, |
||
| 708 | string $as = '', |
||
| 709 | string|DataType $type = DataType::LONG, |
||
| 710 | ?Closure $filterBuilder = null |
||
| 711 | ): self { |
||
| 712 | 2 | $this->aggregations[] = $this->buildFilteredAggregation( |
|
| 713 | 2 | new LastAggregator($metric, $as, $type), |
|
| 714 | 2 | $filterBuilder |
|
| 715 | 2 | ); |
|
| 716 | |||
| 717 | 2 | return $this; |
|
| 718 | } |
||
| 719 | |||
| 720 | /** |
||
| 721 | * Get the last metric found based on the applied group-by filters. |
||
| 722 | * So if you group by the dimension "countries", you can get the last "metric" per country. |
||
| 723 | * |
||
| 724 | * NOTE: This is different from the ELOQUENT last() method! |
||
| 725 | * |
||
| 726 | * @param string $metric |
||
| 727 | * @param string $as |
||
| 728 | * @param \Closure|null $filterBuilder A closure which receives a FilterBuilder. When given, we will only apply the |
||
| 729 | * "last" function to the records which match with the given filter. |
||
| 730 | * |
||
| 731 | * @return $this |
||
| 732 | */ |
||
| 733 | 1 | public function longLast(string $metric, string $as = '', ?Closure $filterBuilder = null): self |
|
| 734 | { |
||
| 735 | 1 | return $this->last($metric, $as, DataType::LONG, $filterBuilder); |
|
| 736 | } |
||
| 737 | |||
| 738 | /** |
||
| 739 | * Get the last metric found based on the applied group-by filters. |
||
| 740 | * So if you group by the dimension "countries", you can get the last "metric" per country. |
||
| 741 | * |
||
| 742 | * NOTE: This is different from the ELOQUENT last() method! |
||
| 743 | * |
||
| 744 | * @param string $metric |
||
| 745 | * @param string $as |
||
| 746 | * @param \Closure|null $filterBuilder A closure which receives a FilterBuilder. When given, we will only apply the |
||
| 747 | * "last" function to the records which match with the given filter. |
||
| 748 | * |
||
| 749 | * @return $this |
||
| 750 | */ |
||
| 751 | 1 | public function floatLast(string $metric, string $as = '', ?Closure $filterBuilder = null): self |
|
| 752 | { |
||
| 753 | 1 | return $this->last($metric, $as, DataType::FLOAT, $filterBuilder); |
|
| 754 | } |
||
| 755 | |||
| 756 | /** |
||
| 757 | * Get the last metric found based on the applied group-by filters. |
||
| 758 | * So if you group by the dimension "countries", you can get the last "metric" per country. |
||
| 759 | * |
||
| 760 | * NOTE: This is different from the ELOQUENT last() method! |
||
| 761 | * |
||
| 762 | * @param string $metric |
||
| 763 | * @param string $as |
||
| 764 | * @param \Closure|null $filterBuilder A closure which receives a FilterBuilder. When given, we will only apply the |
||
| 765 | * "last" function to the records which match with the given filter. |
||
| 766 | * |
||
| 767 | * @return $this |
||
| 768 | */ |
||
| 769 | 1 | public function doubleLast(string $metric, string $as = '', ?Closure $filterBuilder = null): self |
|
| 770 | { |
||
| 771 | 1 | return $this->last($metric, $as, DataType::DOUBLE, $filterBuilder); |
|
| 772 | } |
||
| 773 | |||
| 774 | /** |
||
| 775 | * Get the last metric found based on the applied group-by filters. |
||
| 776 | * So if you group by the dimension "countries", you can get the last "metric" per country. |
||
| 777 | * |
||
| 778 | * NOTE: This is different from the ELOQUENT last() method! |
||
| 779 | * |
||
| 780 | * @param string $metric |
||
| 781 | * @param string $as |
||
| 782 | * @param \Closure|null $filterBuilder A closure which receives a FilterBuilder. When given, we will only apply the |
||
| 783 | * "last" function to the records which match with the given filter. |
||
| 784 | * |
||
| 785 | * @return $this |
||
| 786 | */ |
||
| 787 | 1 | public function stringLast(string $metric, string $as = '', ?Closure $filterBuilder = null): self |
|
| 788 | { |
||
| 789 | 1 | return $this->last($metric, $as, DataType::STRING, $filterBuilder); |
|
| 790 | } |
||
| 791 | |||
| 792 | /** |
||
| 793 | * Computes an arbitrary JavaScript function over a set of columns (both metrics and dimensions are allowed). Your |
||
| 794 | * JavaScript functions are expected to return floating-point values. |
||
| 795 | * |
||
| 796 | * Note: JavaScript-based functionality is disabled by default. Please refer to the Druid JavaScript programming |
||
| 797 | * guide for guidelines about using Druid's JavaScript functionality, including instructions on how to enable it. |
||
| 798 | * |
||
| 799 | * @param string $as The output name as the result will be available |
||
| 800 | * @param string[] $fieldNames The columns which will be given to the fnAggregate function. Both metrics |
||
| 801 | * and dimensions are allowed. |
||
| 802 | * @param string $fnAggregate A javascript function which does the aggregation. This function will receive |
||
| 803 | * the "current" value as first parameter. The other parameters will be the |
||
| 804 | * values of the columns as given in the $fieldNames parameter. |
||
| 805 | * @param string $fnCombine A function which can combine two aggregation results. |
||
| 806 | * @param string $fnReset A function which will reset a value. |
||
| 807 | * @param \Closure|null $filterBuilder A closure which receives a FilterBuilder. When given, we will only apply the |
||
| 808 | * javascript function to the records which match with the given filter. |
||
| 809 | * |
||
| 810 | * @return $this |
||
| 811 | */ |
||
| 812 | 1 | public function javascript( |
|
| 813 | string $as, |
||
| 814 | array $fieldNames, |
||
| 815 | string $fnAggregate, |
||
| 816 | string $fnCombine, |
||
| 817 | string $fnReset, |
||
| 818 | ?Closure $filterBuilder = null |
||
| 819 | ): self { |
||
| 820 | 1 | $this->aggregations[] = $this->buildFilteredAggregation( |
|
| 821 | 1 | new JavascriptAggregator($fieldNames, $as, $fnAggregate, $fnCombine, $fnReset), |
|
| 822 | 1 | $filterBuilder |
|
| 823 | 1 | ); |
|
| 824 | |||
| 825 | 1 | return $this; |
|
| 826 | } |
||
| 827 | } |