use std::collections::HashMap;
use serde::{Deserialize, Serialize};
use serde_with::skip_serializing_none;
use crate::{AdvancedFilter, PropertyIdentifier};
use super::LastUpdatedTimeFilter;
#[skip_serializing_none]
#[derive(Debug, Default, Clone, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct Bounds<T> {
pub min: Option<T>,
pub max: Option<T>,
}
#[skip_serializing_none]
#[derive(Debug, Default, Clone, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct SimpleAggregate {
pub property: Vec<String>,
}
#[skip_serializing_none]
#[derive(Debug, Default, Clone, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct UniqueValuesAggregate {
pub property: Vec<String>,
pub aggregates: Option<HashMap<String, RecordsAggregate>>,
pub size: Option<u32>,
}
#[skip_serializing_none]
#[derive(Debug, Default, Clone, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct NumberHistogramAggregate {
pub property: Vec<String>,
pub hard_bounds: Option<Bounds<f64>>,
pub interval: f64,
pub aggregates: Option<HashMap<String, RecordsAggregate>>,
}
#[derive(Serialize, Deserialize, Clone, Debug)]
pub enum CalendarInterval {
#[serde(rename = "1y")]
Year,
#[serde(rename = "1q")]
Quarter,
#[serde(rename = "1M")]
Month,
#[serde(rename = "1w")]
Week,
#[serde(rename = "1d")]
Day,
#[serde(rename = "1h")]
Hour,
#[serde(rename = "1m")]
Minute,
#[serde(rename = "1s")]
Second,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub enum TimeHistogramInterval {
CalendarInterval(CalendarInterval),
FixedInterval(String),
}
#[skip_serializing_none]
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct TimeHistogramAggregate {
pub property: Vec<String>,
#[serde(flatten)]
pub interval: TimeHistogramInterval,
pub hard_bounds: Option<Bounds<String>>,
pub aggregates: Option<HashMap<String, RecordsAggregate>>,
}
#[derive(Serialize, Deserialize, Clone, Debug)]
pub enum MovingFunction {
#[serde(rename = "MovingFunctions.max")]
Max,
#[serde(rename = "MovingFunctions.min")]
Min,
#[serde(rename = "MovingFunctions.sum")]
Sum,
#[serde(rename = "MovingFunctions.unweightedAvg")]
UnweightedAvg,
#[serde(rename = "MovingFunctions.linearWeightedAvg")]
LinearWeightedAvg,
#[serde(untagged)]
Other(String),
}
#[skip_serializing_none]
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct MovingFunctionAggregate {
pub buckets_path: String,
pub window: u32,
pub function: MovingFunction,
}
#[skip_serializing_none]
#[derive(Debug, Clone, Default, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct FilterAggregate {
pub filters: Vec<AdvancedFilter>,
pub aggregates: Option<HashMap<String, RecordsAggregate>>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub enum RecordsAggregate {
Avg(SimpleAggregate),
Count(SimpleAggregate),
Min(SimpleAggregate),
Max(SimpleAggregate),
Sum(SimpleAggregate),
UniqueValues(UniqueValuesAggregate),
NumberHistogram(NumberHistogramAggregate),
TimeHistogram(TimeHistogramAggregate),
MovingFunction(MovingFunctionAggregate),
Filters(FilterAggregate),
}
impl RecordsAggregate {
pub fn average(property: impl PropertyIdentifier) -> Self {
RecordsAggregate::Avg(SimpleAggregate {
property: property.into_identifier(),
})
}
pub fn count(property: impl PropertyIdentifier) -> Self {
RecordsAggregate::Count(SimpleAggregate {
property: property.into_identifier(),
})
}
pub fn min(property: impl PropertyIdentifier) -> Self {
RecordsAggregate::Min(SimpleAggregate {
property: property.into_identifier(),
})
}
pub fn max(property: impl PropertyIdentifier) -> Self {
RecordsAggregate::Max(SimpleAggregate {
property: property.into_identifier(),
})
}
pub fn sum(property: impl PropertyIdentifier) -> Self {
RecordsAggregate::Sum(SimpleAggregate {
property: property.into_identifier(),
})
}
pub fn unique_values(
property: impl PropertyIdentifier,
size: Option<u32>,
aggregates: Option<HashMap<String, RecordsAggregate>>,
) -> Self {
RecordsAggregate::UniqueValues(UniqueValuesAggregate {
property: property.into_identifier(),
size,
aggregates,
})
}
pub fn number_histogram(
property: impl PropertyIdentifier,
interval: f64,
hard_bounds: Option<Bounds<f64>>,
aggregates: Option<HashMap<String, RecordsAggregate>>,
) -> Self {
RecordsAggregate::NumberHistogram(NumberHistogramAggregate {
property: property.into_identifier(),
hard_bounds,
interval,
aggregates,
})
}
pub fn time_histogram(
property: impl PropertyIdentifier,
interval: TimeHistogramInterval,
hard_bounds: Option<Bounds<String>>,
aggregates: Option<HashMap<String, RecordsAggregate>>,
) -> Self {
RecordsAggregate::TimeHistogram(TimeHistogramAggregate {
property: property.into_identifier(),
interval,
hard_bounds,
aggregates,
})
}
pub fn moving_function(
buckets_path: impl Into<String>,
window: u32,
function: MovingFunction,
) -> Self {
RecordsAggregate::MovingFunction(MovingFunctionAggregate {
buckets_path: buckets_path.into(),
window,
function,
})
}
pub fn filters(
filters: Vec<AdvancedFilter>,
aggregates: Option<HashMap<String, RecordsAggregate>>,
) -> Self {
RecordsAggregate::Filters(FilterAggregate {
filters,
aggregates,
})
}
}
#[skip_serializing_none]
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct RecordsAggregateRequest {
pub last_updated_time: LastUpdatedTimeFilter,
pub filter: Option<AdvancedFilter>,
pub aggregates: HashMap<String, RecordsAggregate>,
}
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
#[serde(untagged)]
pub enum AggregateValue {
String(String),
Integer(i64),
Number(f64),
Boolean(bool),
}
impl From<String> for AggregateValue {
fn from(value: String) -> Self {
AggregateValue::String(value)
}
}
impl<'a> From<&'a str> for AggregateValue {
fn from(value: &'a str) -> Self {
AggregateValue::String(value.to_string())
}
}
impl From<i64> for AggregateValue {
fn from(value: i64) -> Self {
AggregateValue::Integer(value)
}
}
impl From<f64> for AggregateValue {
fn from(value: f64) -> Self {
AggregateValue::Number(value)
}
}
impl From<bool> for AggregateValue {
fn from(value: bool) -> Self {
AggregateValue::Boolean(value)
}
}
#[skip_serializing_none]
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct UniqueValuesBucket {
pub count: u64,
pub value: AggregateValue,
pub aggregates: Option<HashMap<String, AggregateResult>>,
}
#[skip_serializing_none]
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct HistogramBucket<T> {
pub count: u64,
pub interval_start: T,
pub aggregates: Option<HashMap<String, AggregateResult>>,
}
#[skip_serializing_none]
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct FilterBucket {
pub count: u64,
pub aggregates: Option<HashMap<String, AggregateResult>>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(untagged)]
pub enum AggregateBuckets {
UniqueValues(Vec<UniqueValuesBucket>),
NumberHistogram(Vec<HistogramBucket<f64>>),
TimeHistogram(Vec<HistogramBucket<String>>),
Filter(Vec<FilterBucket>),
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub enum AggregateResult {
Avg(f64),
Count(u64),
Min(f64),
Max(f64),
Sum(f64),
Buckets(AggregateBuckets),
MovingFunction(f64),
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct RecordsAggregateResult {
pub aggregates: HashMap<String, AggregateResult>,
}