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 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181
use crate::search::*;
use crate::util::*;
#[derive(Debug, Clone, Serialize, PartialEq)]
/// A multi-bucket aggregation that groups geo_point and geo_shape values into buckets that represent a grid.
/// The resulting grid can be sparse and only contains cells that have matching data. Each cell corresponds to
/// a map tile as used by many online map sites. Each cell is labeled using a "{zoom}/{x}/{y}" format, where
/// zoom is equal to the user-specified precision.
///
/// <https://www.elastic.co/guide/en/elasticsearch/reference/current/search-aggregations-bucket-geotilegrid-aggregation.html>
pub struct GeotileGridAggregation {
geotile_grid: GeotileGridAggregationInner,
#[serde(skip_serializing_if = "ShouldSkip::should_skip")]
aggs: Aggregations,
}
#[derive(Debug, Clone, Serialize, PartialEq)]
struct GeotileGridAggregationInner {
field: String,
#[serde(skip_serializing_if = "ShouldSkip::should_skip")]
precision: Option<u8>,
#[serde(skip_serializing_if = "ShouldSkip::should_skip")]
bounds: Option<GeoBoundingBox>,
#[serde(skip_serializing_if = "ShouldSkip::should_skip")]
size: Option<u64>,
#[serde(skip_serializing_if = "ShouldSkip::should_skip")]
shard_size: Option<u64>,
}
impl Aggregation {
/// Creates an instance of [`GeotileGridAggregation`]
///
/// - `field` - field to group by
pub fn geotile_grid<T>(field: T) -> GeotileGridAggregation
where
T: ToString,
{
GeotileGridAggregation {
geotile_grid: GeotileGridAggregationInner {
field: field.to_string(),
precision: None,
bounds: None,
size: None,
shard_size: None,
},
aggs: Aggregations::new(),
}
}
}
impl GeotileGridAggregation {
/// The `size` parameter can be set to define the maximum number of buckets to return.Defaults to 10,000.
/// When results are trimmed, buckets are prioritized based on the volume of documents they contain.
pub fn size(mut self, size: u64) -> Self {
self.geotile_grid.size = Some(size);
self
}
/// The `shard_size` parameter limits the number of buckets returned from each shard.
/// Defaults to max(10,(size x number-of-shards)) to allow for a more accurate count of
/// the top cells in the final result.Since each shard could have a different top result order,
/// using a larger number here reduces the risk of inaccurate counts, but incurs a performance cost.
pub fn shard_size(mut self, shard_size: u64) -> Self {
self.geotile_grid.shard_size = Some(shard_size);
self
}
/// the `precision` parameter is used to define cells/buckets in the results. Defaults to 7.
/// Values outside of \[0,29\] will be rejected.
pub fn precision(mut self, precision: u8) -> Self {
self.geotile_grid.precision = Some(precision);
self
}
/// the `bounds` parameter defines the bounding box used to filter the geo-points or geo-shapes in each bucket.
/// Accepts the same bounding box formats as the [`GeoBoundingBoxQuery`]
pub fn bounds<T>(mut self, bounds: T) -> Self
where
T: Into<GeoBoundingBox>,
{
self.geotile_grid.bounds = Some(bounds.into());
self
}
add_aggregate!();
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn serialization() {
assert_serialize_aggregation(
Aggregation::geotile_grid("test_field"),
json!({ "geotile_grid": { "field": "test_field" } }),
);
assert_serialize_aggregation(
Aggregation::geotile_grid("test_field")
.size(5)
.precision(18)
.shard_size(100)
.bounds(GeoBoundingBox::Vertices {
top: 5.0,
left: 52.4,
bottom: 4.9,
right: 52.3,
}),
json!({
"geotile_grid": {
"field": "test_field",
"size": 5,
"precision": 18,
"shard_size": 100,
"bounds": {
"top": 5.0,
"left": 52.4,
"bottom": 4.9,
"right": 52.3,
}
}
}),
);
assert_serialize_aggregation(
Aggregation::geotile_grid("test_field")
.size(0)
.precision(22)
.shard_size(16)
.bounds(GeoBoundingBox::Vertices {
top: 25.0,
left: 102.4,
bottom: 7.9,
right: 152.3,
})
.aggregate(
"test_sub_agg",
Aggregation::geotile_grid("test_field2")
.size(2)
.precision(12)
.shard_size(22)
.bounds(GeoBoundingBox::WellKnownText {
wkt: "BBOX (-74.1, -71.12, 40.73, 40.01)".to_string(),
}),
),
json!({
"geotile_grid": {
"field": "test_field",
"size": 0,
"precision": 22,
"shard_size": 16,
"bounds": {
"top": 25.0,
"left": 102.4,
"bottom": 7.9,
"right": 152.3,
}
},
"aggs": {
"test_sub_agg": {
"geotile_grid": {
"field": "test_field2",
"size": 2,
"precision": 12,
"shard_size": 22,
"bounds":{
"wkt": "BBOX (-74.1, -71.12, 40.73, 40.01)"
}
}
}
}
}),
);
}
}