1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
use crate::search::*;
use crate::util::*;
use serde::Serialize;

/// A special single-bucket aggregation that enables aggregating nested documents.
///
/// <https://www.elastic.co/guide/en/elasticsearch/reference/current/search-aggregations-bucket-nested-aggregation.html>
#[derive(Debug, Clone, Serialize, PartialEq)]
pub struct NestedAggregation {
    nested: NestedAggregationInner,

    #[serde(skip_serializing_if = "ShouldSkip::should_skip")]
    aggs: Aggregations,
}

#[derive(Debug, Clone, Serialize, PartialEq)]
struct NestedAggregationInner {
    path: String,
}

impl Aggregation {
    /// Creates an instance of [`NestedAggregation`]
    ///
    /// - `path` - The nested path to aggregate.
    pub fn nested(path: &str) -> NestedAggregation {
        NestedAggregation {
            nested: NestedAggregationInner {
                path: path.to_string(),
            },
            aggs: Aggregations::new(),
        }
    }
}

impl NestedAggregation {
    add_aggregate!();
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn serialization() {
        assert_serialize_aggregation(
            Aggregation::nested("nested_path"),
            json!({ "nested": { "path": "nested_path" } }),
        );

        assert_serialize_aggregation(
            Aggregation::nested("nested_path")
                .aggregate("sub_agg", Aggregation::terms("test_field")),
            json!({
                "nested": {
                    "path": "nested_path"
                },
                "aggs": {
                    "sub_agg": {
                        "terms": {
                            "field": "test_field"
                        }
                    }
                }
            }),
        );
    }
}