elasticsearch_dsl/search/queries/geo/
geo_distance_query.rs

1use crate::search::*;
2use crate::util::*;
3
4/// Matches [geo_point](https://www.elastic.co/guide/en/elasticsearch/reference/current/geo-point.html)
5/// and [geo_shape](https://www.elastic.co/guide/en/elasticsearch/reference/current/geo-shape.html)
6/// values within a given distance of a geopoint.
7///
8/// <https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-geo-distance-query.html>
9#[derive(Debug, Clone, PartialEq, Serialize)]
10#[serde(remote = "Self")]
11pub struct GeoDistanceQuery {
12    #[serde(skip)]
13    field: String,
14
15    #[serde(skip)]
16    location: GeoLocation,
17
18    distance: Distance,
19
20    #[serde(skip_serializing_if = "ShouldSkip::should_skip")]
21    distance_type: Option<GeoDistanceType>,
22
23    #[serde(skip_serializing_if = "ShouldSkip::should_skip")]
24    validation_method: Option<ValidationMethod>,
25
26    #[serde(skip_serializing_if = "ShouldSkip::should_skip")]
27    boost: Option<f32>,
28
29    #[serde(skip_serializing_if = "ShouldSkip::should_skip")]
30    _name: Option<String>,
31}
32
33impl Query {
34    /// Creates an instance of [`GeoDistanceQuery`]
35    ///
36    /// - `field` - Field you wish to search
37    /// - `origin` - GeoPoint to measure distance to
38    /// - `distance` - Distance threshold
39    pub fn geo_distance<T, U, V>(field: T, origin: U, distance: V) -> GeoDistanceQuery
40    where
41        T: ToString,
42        U: Into<GeoLocation>,
43        V: Into<Distance>,
44    {
45        GeoDistanceQuery {
46            field: field.to_string(),
47            location: origin.into(),
48            distance: distance.into(),
49            distance_type: None,
50            validation_method: None,
51            boost: None,
52            _name: None,
53        }
54    }
55}
56
57impl GeoDistanceQuery {
58    /// Set to `IGNORE_MALFORMED` to accept geo points with invalid latitude or longitude, set to
59    /// `COERCE` to also try to infer correct latitude or longitude. (default is `STRICT`).
60    pub fn validation_method(mut self, validation_method: ValidationMethod) -> Self {
61        self.validation_method = Some(validation_method);
62        self
63    }
64
65    /// How to compute the distance. Can either be [Arc](GeoDistanceType::Arc) (default), or
66    /// [Plane](GeoDistanceType::Plane) (faster, but inaccurate on long distances and close to the
67    /// poles).
68    pub fn distance_type(mut self, distance_type: GeoDistanceType) -> Self {
69        self.distance_type = Some(distance_type);
70        self
71    }
72
73    add_boost_and_name!();
74}
75
76impl ShouldSkip for GeoDistanceQuery {}
77
78serialize_with_root_key_value_pair!("geo_distance": GeoDistanceQuery, field, location);
79
80#[cfg(test)]
81mod tests {
82    use super::*;
83
84    #[test]
85    fn serialization() {
86        assert_serialize_query(
87            Query::geo_distance(
88                "pin.location",
89                GeoLocation::new(40.12, -71.34),
90                Distance::Kilometers(300),
91            ),
92            json!({
93                "geo_distance": {
94                    "distance": "300km",
95                    "pin.location": [-71.34, 40.12],
96                }
97            }),
98        );
99
100        assert_serialize_query(
101            Query::geo_distance(
102                "pin.location",
103                GeoLocation::new(40.12, -71.34),
104                Distance::Kilometers(300),
105            )
106            .distance_type(GeoDistanceType::Plane)
107            .validation_method(ValidationMethod::Strict)
108            .name("test_name")
109            .boost(1),
110            json!({
111                "geo_distance": {
112                    "distance": "300km",
113                    "distance_type": "plane",
114                    "pin.location": [-71.34, 40.12],
115                    "validation_method": "STRICT",
116                    "_name": "test_name",
117                    "boost": 1.0,
118                }
119            }),
120        );
121    }
122}