elasticsearch_dsl/search/queries/shape/
shape_query.rs

1use crate::search::*;
2use crate::util::*;
3use serde::Serialize;
4
5/// Queries documents that contain fields indexed using the `shape` type.
6///
7/// Requires the [`shape` Mapping](https://www.elastic.co/guide/en/elasticsearch/reference/current/shape.html).
8///
9/// <https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-shape-query.html>
10#[derive(Debug, Clone, PartialEq, Serialize)]
11#[serde(remote = "Self")]
12pub struct ShapeQuery {
13    #[serde(skip)]
14    field: String,
15
16    #[serde(skip)]
17    shape: InlineShape,
18
19    #[serde(skip_serializing_if = "ShouldSkip::should_skip")]
20    ignore_unmapped: Option<bool>,
21
22    #[serde(skip_serializing_if = "ShouldSkip::should_skip")]
23    boost: Option<f32>,
24
25    #[serde(skip_serializing_if = "ShouldSkip::should_skip")]
26    _name: Option<String>,
27}
28
29#[derive(Debug, Clone, PartialEq, Serialize)]
30struct InlineShape {
31    shape: Shape,
32
33    #[serde(skip_serializing_if = "ShouldSkip::should_skip")]
34    relation: Option<SpatialRelation>,
35}
36
37impl Query {
38    /// Creates an instance of [`ShapeQuery`]
39    ///
40    /// - `field` - Field you wish to search
41    /// - `shape` - Shape you with to search
42    pub fn shape<S, T>(field: S, shape: T) -> ShapeQuery
43    where
44        S: ToString,
45        T: Into<Shape>,
46    {
47        ShapeQuery {
48            field: field.to_string(),
49            shape: InlineShape {
50                shape: shape.into(),
51                relation: None,
52            },
53            ignore_unmapped: None,
54            boost: None,
55            _name: None,
56        }
57    }
58}
59
60impl ShapeQuery {
61    /// The [shape strategy](https://www.elastic.co/guide/en/elasticsearch/reference/current/geo-shape.html#spatial-strategy)
62    /// mapping parameter determines which spatial relation operators may be
63    /// used at search time.
64    pub fn relation(mut self, relation: SpatialRelation) -> Self {
65        self.shape.relation = Some(relation);
66        self
67    }
68
69    /// When set to true the `ignore_unmapped` option will ignore an unmapped
70    /// field and will not match any documents for this query. This can be
71    /// useful when querying multiple indexes which might have different
72    /// mappings. When set to `false` (the default value) the query will throw
73    /// an exception if the field is not mapped.
74    pub fn ignore_unmapped(mut self, ignore_unmapped: bool) -> Self {
75        self.ignore_unmapped = Some(ignore_unmapped);
76        self
77    }
78
79    add_boost_and_name!();
80}
81
82impl ShouldSkip for ShapeQuery {}
83
84serialize_with_root_key_value_pair!("shape": ShapeQuery, field, shape);
85
86#[cfg(test)]
87mod tests {
88    use super::*;
89
90    #[test]
91    fn test_serialization() {
92        assert_serialize_query(
93            Query::shape("pin.location", Shape::point([2.2, 1.1])),
94            json!({
95                "shape": {
96                    "pin.location": {
97                        "shape": {
98                            "type": "point",
99                            "coordinates": [2.2, 1.1]
100                        }
101                    },
102                }
103            }),
104        );
105
106        assert_serialize_query(
107            Query::shape("pin.location", Shape::point([2.2, 1.1]))
108                .boost(2)
109                .name("test")
110                .ignore_unmapped(true)
111                .relation(SpatialRelation::Within),
112            json!({
113                "shape": {
114                    "_name": "test",
115                    "boost": 2.0,
116                    "ignore_unmapped": true,
117                    "pin.location": {
118                        "shape": {
119                            "type": "point",
120                            "coordinates": [2.2, 1.1]
121                        },
122                        "relation": "WITHIN"
123                    },
124                }
125            }),
126        );
127    }
128}