-
Notifications
You must be signed in to change notification settings - Fork 6
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
First real support for pipeline aggregation:
cumulative_sum
(#63)
It's our first pipeline aggregation, so it's a basis for all other PRs. It introduces some general logic for them, so calculating results for some aggregation not based on rows returned from a query to Clickhouse, but from returned rows for some other aggregation. Some example charts: <img width="1728" alt="Screenshot 2024-05-13 at 19 47 19" src="https://github.com/QuesmaOrg/quesma/assets/5407146/b05ec180-8c98-4a42-afaa-8443e88cb37c"> <img width="1724" alt="Screenshot 2024-05-13 at 19 46 12" src="https://github.com/QuesmaOrg/quesma/assets/5407146/058814ec-9e36-4729-8246-16fb521107af">
- Loading branch information
Showing
18 changed files
with
1,074 additions
and
128 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,88 @@ | ||
package pipeline_aggregations | ||
|
||
import ( | ||
"context" | ||
"fmt" | ||
"mitmproxy/quesma/logger" | ||
"mitmproxy/quesma/model" | ||
"mitmproxy/quesma/util" | ||
) | ||
|
||
// We fully support this aggregation. | ||
// Description: A parent pipeline aggregation which calculates the cumulative sum of a specified metric | ||
// in a parent histogram (or date_histogram) aggregation. | ||
// The specified metric must be numeric and the enclosing histogram must have min_doc_count set to 0 (default for histogram aggregations). | ||
// https://www.elastic.co/guide/en/elasticsearch/reference/current/search-aggregations-pipeline-cumulative-sum-aggregation.html | ||
|
||
type CumulativeSum struct { | ||
ctx context.Context | ||
Parent string | ||
IsCount bool // count is a special case, `bucketsPath` is not a path to another aggregation, but path-to-aggregation>_count | ||
} | ||
|
||
func NewCumulativeSum(ctx context.Context, bucketsPath string) CumulativeSum { | ||
isCount := bucketsPath == bucketsPathCount | ||
return CumulativeSum{ctx: ctx, Parent: bucketsPath, IsCount: isCount} | ||
} | ||
|
||
const bucketsPathCount = "_count" // special name for `buckets_path` parameter, normally it's some other aggregation's name | ||
|
||
func (query CumulativeSum) IsBucketAggregation() bool { | ||
return false | ||
} | ||
|
||
func (query CumulativeSum) TranslateSqlResponseToJson(rows []model.QueryResultRow, level int) []model.JsonMap { | ||
if len(rows) == 0 { | ||
logger.WarnWithCtx(query.ctx).Msg("no rows returned for cumulative sum aggregation") | ||
return []model.JsonMap{{}} | ||
} | ||
var response []model.JsonMap | ||
for _, row := range rows { | ||
response = append(response, model.JsonMap{"value": row.Cols[len(row.Cols)-1].Value}) | ||
} | ||
return response | ||
} | ||
|
||
func (query CumulativeSum) CalculateResultWhenMissing(parentRow model.QueryResultRow, previousResultsCurrentAggregation []model.QueryResultRow) model.QueryResultRow { | ||
resultRow := parentRow.Copy() // result is the same as parent, with an exception of last element, which we'll change below | ||
parentValue := parentRow.Cols[len(parentRow.Cols)-1].Value | ||
var resultValue any | ||
if len(previousResultsCurrentAggregation) == 0 { | ||
resultValue = parentValue | ||
} else { | ||
// I don't check types too much, they are expected to be numeric, so either floats or ints. | ||
// I propose to keep it this way until at least one case arises as this method can be called a lot of times. | ||
previousValue := previousResultsCurrentAggregation[len(previousResultsCurrentAggregation)-1].Cols[len(previousResultsCurrentAggregation[len(previousResultsCurrentAggregation)-1].Cols)-1].Value | ||
parentValueAsFloat, ok := util.ExtractFloat64Maybe(parentValue) | ||
if ok { | ||
previousValueAsFloat, ok := util.ExtractFloat64Maybe(previousValue) | ||
if ok { | ||
resultValue = parentValueAsFloat + previousValueAsFloat | ||
} else { | ||
logger.WarnWithCtx(query.ctx).Msgf("could not convert previous value to float: %v, parentValue: %v", previousValue, parentValue) | ||
resultValue = previousValue | ||
} | ||
} else { | ||
previousValueAsInt, okPrevious := util.ExtractInt64Maybe(previousValue) | ||
parentValueAsInt, okParent := util.ExtractInt64Maybe(parentValue) | ||
if okPrevious && okParent { | ||
resultValue = parentValueAsInt + previousValueAsInt | ||
} else if okPrevious { | ||
logger.WarnWithCtx(query.ctx).Msgf("could not convert parent value to int: %v, previousValue: %v. Using previousValue as sum", parentValue, previousValue) | ||
resultValue = previousValue | ||
} else if okParent { | ||
logger.WarnWithCtx(query.ctx).Msgf("could not convert previous value to int: %v, parentValue: %v. Starting sum from 0", previousValue, parentValue) | ||
resultValue = parentValue | ||
} else { | ||
logger.WarnWithCtx(query.ctx).Msgf("could not convert previous and parent value to int, previousValue: %v, parentValue: %v. Using nil as result", previousValue, parentValue) | ||
resultValue = nil | ||
} | ||
} | ||
} | ||
resultRow.Cols[len(resultRow.Cols)-1].Value = resultValue | ||
return resultRow | ||
} | ||
|
||
func (query CumulativeSum) String() string { | ||
return fmt.Sprintf("cumulative_sum(%s)", query.Parent) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.