elasticsearch_dsl/search/sort/
geo_distance_sort.rs1use super::{SortMode, SortOrder};
2use crate::util::{KeyValuePair, ShouldSkip};
3use crate::{DistanceUnit, GeoDistanceType, GeoLocation};
4use serde::Serialize;
5
6#[derive(Debug, Clone, PartialEq, Serialize)]
10#[serde(remote = "Self")]
11pub struct GeoDistanceSort {
12 #[serde(skip)]
13 field: String,
14
15 #[serde(skip)]
16 points: Vec<GeoLocation>,
17
18 #[serde(skip_serializing_if = "ShouldSkip::should_skip")]
19 order: Option<SortOrder>,
20
21 #[serde(skip_serializing_if = "ShouldSkip::should_skip")]
22 unit: Option<DistanceUnit>,
23
24 #[serde(skip_serializing_if = "ShouldSkip::should_skip")]
25 mode: Option<SortMode>,
26
27 #[serde(skip_serializing_if = "ShouldSkip::should_skip")]
28 distance_type: Option<GeoDistanceType>,
29
30 #[serde(skip_serializing_if = "ShouldSkip::should_skip")]
31 ignore_unmapped: Option<bool>,
32}
33
34impl GeoDistanceSort {
35 pub fn new<T, U>(field: T, points: U) -> Self
37 where
38 T: ToString,
39 U: IntoIterator,
40 U::Item: Into<GeoLocation>,
41 {
42 Self {
43 field: field.to_string(),
44 points: points.into_iter().map(Into::into).collect(),
45 order: None,
46 unit: None,
47 mode: None,
48 distance_type: None,
49 ignore_unmapped: None,
50 }
51 }
52
53 pub fn ascending<T, U>(field: T, points: U) -> Self
55 where
56 T: ToString,
57 U: IntoIterator,
58 U::Item: Into<GeoLocation>,
59 {
60 Self::new(field, points).order(SortOrder::Asc)
61 }
62
63 pub fn descending<T, U>(field: T, points: U) -> Self
65 where
66 T: ToString,
67 U: IntoIterator,
68 U::Item: Into<GeoLocation>,
69 {
70 Self::new(field, points).order(SortOrder::Desc)
71 }
72
73 pub fn order(mut self, order: SortOrder) -> Self {
77 self.order = Some(order);
78 self
79 }
80
81 pub fn unit(mut self, unit: DistanceUnit) -> Self {
85 self.unit = Some(unit);
86 self
87 }
88
89 pub fn mode(mut self, mode: SortMode) -> Self {
93 self.mode = Some(mode);
94 self
95 }
96
97 pub fn distance_type(mut self, distance_type: GeoDistanceType) -> Self {
101 self.distance_type = Some(distance_type);
102 self
103 }
104
105 pub fn ignore_unmapped(mut self, ignore_unmapped: bool) -> Self {
111 self.ignore_unmapped = Some(ignore_unmapped);
112 self
113 }
114}
115
116impl IntoIterator for GeoDistanceSort {
117 type Item = Self;
118
119 type IntoIter = std::option::IntoIter<Self::Item>;
120
121 fn into_iter(self) -> Self::IntoIter {
122 Some(self).into_iter()
123 }
124}
125
126serialize_with_root_key_value_pair!("_geo_distance": GeoDistanceSort, field, points);
127
128#[cfg(test)]
129mod tests {
130 use super::*;
131 use crate::util::assert_serialize;
132
133 #[test]
134 fn serialization() {
135 assert_serialize(
136 GeoDistanceSort::new("test", GeoLocation::new(1.2, 3.3)),
137 json!({
138 "_geo_distance": {
139 "test": [ [3.3, 1.2] ]
140 }
141 }),
142 );
143
144 assert_serialize(
145 GeoDistanceSort::ascending("test", GeoLocation::new(1.2, 3.3)),
146 json!({
147 "_geo_distance": {
148 "test": [ [3.3, 1.2] ],
149 "order": "asc",
150 }
151 }),
152 );
153
154 assert_serialize(
155 GeoDistanceSort::descending("test", GeoLocation::new(1.2, 3.3))
156 .order(SortOrder::Asc)
157 .unit(DistanceUnit::Inches)
158 .mode(SortMode::Max)
159 .distance_type(GeoDistanceType::Arc)
160 .ignore_unmapped(true),
161 json!({
162 "_geo_distance": {
163 "test": [ [3.3, 1.2] ],
164 "unit": "in",
165 "order": "asc",
166 "mode": "max",
167 "distance_type": "arc",
168 "ignore_unmapped": true,
169 }
170 }),
171 );
172 }
173}