elastic_query_builder/aggregation/
nested_aggregation.rs1use 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 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 }
111}