elasticsearch_dsl/search/aggregations/bucket/
bucket_selector_aggregation.rs1use serde::Serialize;
2
3use crate::search::*;
4use crate::types::Map;
5use crate::util::*;
6
7#[derive(Debug, Clone, PartialEq, Serialize)]
12#[serde(untagged)]
13pub enum BucketsPath {
14 Single(String),
16 Multi(Map<String, String>),
19}
20
21impl From<&str> for BucketsPath {
22 fn from(path: &str) -> Self {
23 BucketsPath::Single(path.to_string())
24 }
25}
26
27impl From<String> for BucketsPath {
28 fn from(path: String) -> Self {
29 BucketsPath::Single(path)
30 }
31}
32
33impl From<Vec<(&str, &str)>> for BucketsPath {
34 fn from(paths: Vec<(&str, &str)>) -> Self {
35 BucketsPath::Multi(
36 paths
37 .into_iter()
38 .map(|(k, v)| (k.to_string(), v.to_string()))
39 .collect(),
40 )
41 }
42}
43
44impl From<Vec<(String, String)>> for BucketsPath {
45 fn from(paths: Vec<(String, String)>) -> Self {
46 BucketsPath::Multi(paths.into_iter().collect())
47 }
48}
49
50#[derive(Debug, Clone, Serialize, PartialEq)]
51pub struct BucketSelectorAggregation {
54 bucket_selector: BucketSelectorAggregationInner,
55
56 #[serde(skip_serializing_if = "ShouldSkip::should_skip")]
57 aggs: Aggregations,
58}
59
60#[derive(Debug, Clone, Serialize, PartialEq)]
61struct BucketSelectorAggregationInner {
62 buckets_path: BucketsPath,
63
64 script: Script,
65
66 #[serde(skip_serializing_if = "ShouldSkip::should_skip")]
67 gap_policy: Option<GapPolicy>,
68
69 #[serde(skip_serializing_if = "ShouldSkip::should_skip")]
70 format: Option<String>,
71}
72
73impl Aggregation {
74 pub fn bucket_selector<B, S>(buckets_path: B, script: S) -> BucketSelectorAggregation
79 where
80 B: Into<BucketsPath>,
81 S: Into<Script>,
82 {
83 BucketSelectorAggregation {
84 bucket_selector: BucketSelectorAggregationInner {
85 buckets_path: buckets_path.into(),
86 script: script.into(),
87 gap_policy: None,
88 format: None,
89 },
90 aggs: Aggregations::new(),
91 }
92 }
93}
94
95impl BucketSelectorAggregation {
96 pub fn gap_policy(mut self, gap_policy: GapPolicy) -> Self {
101 self.bucket_selector.gap_policy = Some(gap_policy);
102 self
103 }
104
105 pub fn format<T>(mut self, format: T) -> Self
109 where
110 T: ToString,
111 {
112 self.bucket_selector.format = Some(format.to_string());
113 self
114 }
115
116 add_aggregate!();
117}
118
119#[cfg(test)]
120mod tests {
121 use super::*;
122
123 #[test]
124 fn serialization() {
125 assert_serialize_aggregation(
126 Aggregation::bucket_selector(
127 "the_sum",
128 Script::source("params.the_sum > 1000").lang("painless"),
129 ),
130 json!({
131 "bucket_selector": {
132 "buckets_path": "the_sum",
133 "script": {
134 "lang": "painless",
135 "source": "params.the_sum > 1000"
136 }
137 }
138 }),
139 );
140
141 assert_serialize_aggregation(
142 Aggregation::bucket_selector(
143 "the_sum",
144 Script::source("params.the_sum > 1000").lang("painless"),
145 )
146 .gap_policy(GapPolicy::Skip)
147 .format("###.00"),
148 json!({
149 "bucket_selector": {
150 "buckets_path": "the_sum",
151 "script": {
152 "lang": "painless",
153 "source": "params.the_sum > 1000"
154 },
155 "gap_policy": "skip",
156 "format": "###.00"
157 }
158 }),
159 );
160
161 assert_serialize_aggregation(
162 Aggregation::bucket_selector(
163 vec![("sum_value", "the_sum")],
164 Script::source("params.sum_value > 1000").lang("painless"),
165 ),
166 json!({
167 "bucket_selector": {
168 "buckets_path": {
169 "sum_value": "the_sum"
170 },
171 "script": {
172 "lang": "painless",
173 "source":"params.sum_value > 1000"
174 }
175 }
176 }),
177 );
178 }
179}