elastic_query_builder/aggregation/
nested_aggregation.rs

1use crate::aggregation::AggregationTrait;
2use crate::merge;
3use serde::ser::SerializeStruct;
4use serde::{Serialize, Serializer};
5use serde_json::{json, Value};
6
7#[derive(Default)]
8pub struct NestedAggregation {
9    name: String,
10    value: NestedValue,
11    aggregation: Value,
12}
13
14#[derive(Default)]
15struct NestedValue {
16    path: String,
17}
18
19impl NestedAggregation {
20    pub fn new(name: &str) -> Self {
21        let term = NestedAggregation {
22            name: name.to_string(),
23            ..Default::default()
24        };
25        term
26    }
27    pub fn set_path(mut self, path: &str) -> Self {
28        self.value.path = path.to_string();
29        self
30    }
31    pub fn append_aggregation<T>(mut self, query: T) -> Self
32    where
33        T: AggregationTrait,
34    {
35        let mut values = self.aggregation.clone();
36        merge(&mut values, &query.build());
37        self.aggregation = json!(values);
38        return self;
39    }
40}
41
42impl Serialize for NestedValue {
43    fn serialize<S>(&self, serializer: S) -> Result<<S as Serializer>::Ok, <S as Serializer>::Error>
44    where
45        S: Serializer,
46    {
47        let mut state = serializer.serialize_struct("TermsBuilder", 0)?;
48
49        if !self.path.is_empty() {
50            state.serialize_field("path", &self.path)?;
51        }
52        state.end()
53    }
54}
55
56impl Serialize for NestedAggregation {
57    fn serialize<S>(&self, serializer: S) -> Result<<S as Serializer>::Ok, <S as Serializer>::Error>
58    where
59        S: Serializer,
60    {
61        let mut state = serializer.serialize_struct("BoolQuery", 0)?;
62        state.serialize_field("nested", &self.value)?;
63        if !(self.aggregation.is_null() || self.aggregation.to_string().is_empty()) {
64            state.serialize_field("aggs", &self.aggregation)?;
65        }
66        // }
67        state.end()
68    }
69}
70
71impl AggregationTrait for NestedAggregation {
72    fn name(&self) -> &str {
73        self.name.as_str()
74    }
75
76    fn build(&self) -> Value {
77        let name = self.name.to_string();
78        json!({ name: self })
79    }
80
81    fn query_name(&self) -> String {
82        "nested".to_string()
83    }
84}
85
86#[cfg(test)]
87mod tests {
88    use super::*;
89    use crate::aggregation::stats_aggregation::StatsAggregation;
90    use crate::aggregation::terms_aggregation::TermsAggregation;
91    use crate::aggregation::AggregationTrait;
92
93    #[test]
94    fn test_nested_aggregation() {
95        let agg = NestedAggregation::new("hoge")
96            .set_path("path")
97            .append_aggregation(NestedAggregation::new("agg"));
98
99        let json = agg.build();
100        println!("{}", json);
101        let agg = NestedAggregation::new("hoge")
102            .set_path("path")
103            .append_aggregation(TermsAggregation::new("agg1").set_field("key"))
104            .append_aggregation(StatsAggregation::new("agg2").set_field("key"));
105
106        let json = agg.build();
107        println!("{}", json);
108        // assert_eq!(json["test"]["nested"]["field"], "test");
109        // assert_eq!(json["test"]["nested"]["size"], 1);
110    }
111}