From 00f8d27693932d3ded91a9ab4f8657f0af7acb96 Mon Sep 17 00:00:00 2001 From: iamazy Date: Thu, 28 Oct 2021 13:18:53 +0800 Subject: [PATCH] Implement metrics aggregations --- .../metrics/cardinality_aggregation.rs | 85 +++++++++++++++++++ src/search/aggregations/metrics/mod.rs | 2 + src/search/aggregations/mod.rs | 1 + 3 files changed, 88 insertions(+) create mode 100644 src/search/aggregations/metrics/cardinality_aggregation.rs diff --git a/src/search/aggregations/metrics/cardinality_aggregation.rs b/src/search/aggregations/metrics/cardinality_aggregation.rs new file mode 100644 index 0000000..cef282b --- /dev/null +++ b/src/search/aggregations/metrics/cardinality_aggregation.rs @@ -0,0 +1,85 @@ +use crate::util::*; +use crate::Aggregation; + +/// A `single-value` metrics aggregation that calculates an approximate count of distinct values. +/// +/// +#[derive(Debug, Clone, Serialize, PartialEq)] +pub struct CardinalityAggregation { + #[serde(skip_serializing)] + pub(crate) name: String, + cardinality: CardinalityAggregationInner, +} + +#[derive(Debug, Clone, Serialize, PartialEq)] +struct CardinalityAggregationInner { + field: String, + + #[serde(skip_serializing_if = "ShouldSkip::should_skip")] + precision_threshold: Option, + + #[serde(skip_serializing_if = "ShouldSkip::should_skip")] + missing: Option, +} + +impl Aggregation { + /// Creates an instance of [`CardinalityAggregation`] + /// + /// - `name` - name of the aggregation + pub fn cardinality( + name: impl Into, + field: impl Into, + ) -> CardinalityAggregation { + CardinalityAggregation { + name: name.into(), + cardinality: CardinalityAggregationInner { + field: field.into(), + precision_threshold: None, + missing: None, + }, + } + } +} + +impl CardinalityAggregation { + /// The `precision_threshold` options allows to trade memory for accuracy, and defines a unique count below + /// which counts are expected to be close to accurate. Above this value, counts might become a bit more fuzzy. + /// The maximum supported value is 40000, thresholds above this number will have the same effect as a threshold + /// of 40000. The default value is 3000 + pub fn precision_threshold(mut self, precision_threshold: impl Into) -> Self { + self.cardinality.precision_threshold = Some(precision_threshold.into()); + self + } + + /// The `missing` parameter defines how documents that are missing a value should be treated. By default they will + /// be ignored but it is also possible to treat them as if they had a value. + pub fn missing(mut self, missing: impl Into) -> Self { + self.cardinality.missing = Some(missing.into()); + self + } +} + +#[cfg(test)] +mod tests { + use super::*; + + test_serialization! { + with_required_fields( + Aggregation::cardinality("test_cardinality", "test_field"), + json!({ "cardinality": { "field": "test_field" } }) + ); + + with_all_fields( + Aggregation::cardinality("test_cardinality", "test_field") + .precision_threshold(100u16) + .missing("N/A"), + json!({ + "cardinality": { + "field": "test_field", + "precision_threshold": 100, + "missing": "N/A" + } + }) + ); + } +} diff --git a/src/search/aggregations/metrics/mod.rs b/src/search/aggregations/metrics/mod.rs index b7c71eb..1452d20 100644 --- a/src/search/aggregations/metrics/mod.rs +++ b/src/search/aggregations/metrics/mod.rs @@ -10,6 +10,8 @@ //! //! +mod cardinality_aggregation; mod top_hits_aggregation; +pub use self::cardinality_aggregation::*; pub use self::top_hits_aggregation::*; diff --git a/src/search/aggregations/mod.rs b/src/search/aggregations/mod.rs index 728f01b..4e972db 100644 --- a/src/search/aggregations/mod.rs +++ b/src/search/aggregations/mod.rs @@ -57,6 +57,7 @@ macro_rules! aggregation { aggregation!(Aggregation { Terms(TermsAggregation), TopHits(TopHitsAggregation), + Cardinality(CardinalityAggregation) }); /// Type alias for a collection of aggregations