elasticsearch_dsl/search/queries/shape/
shape_lookup_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 ShapeLookupQuery {
13    #[serde(skip)]
14    field: String,
15
16    #[serde(skip)]
17    shape: Shape,
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 Shape {
31    indexed_shape: IndexedShape,
32
33    #[serde(skip_serializing_if = "ShouldSkip::should_skip")]
34    relation: Option<SpatialRelation>,
35}
36
37#[derive(Debug, Clone, PartialEq, Serialize)]
38struct IndexedShape {
39    id: String,
40
41    #[serde(skip_serializing_if = "ShouldSkip::should_skip")]
42    index: Option<String>,
43
44    #[serde(skip_serializing_if = "ShouldSkip::should_skip")]
45    path: Option<String>,
46
47    #[serde(skip_serializing_if = "ShouldSkip::should_skip")]
48    routing: Option<String>,
49}
50
51impl Query {
52    /// Creates an instance of [`ShapeLookupQuery`]
53    ///
54    /// - `field` - Field you wish to search
55    /// - `id` - The ID of the document that containing the pre-indexed shape
56    pub fn shape_lookup<S, T>(field: S, id: T) -> ShapeLookupQuery
57    where
58        S: ToString,
59        T: ToString,
60    {
61        ShapeLookupQuery {
62            field: field.to_string(),
63            shape: Shape {
64                indexed_shape: IndexedShape {
65                    id: id.to_string(),
66                    index: None,
67                    path: None,
68                    routing: None,
69                },
70                relation: None,
71            },
72            ignore_unmapped: None,
73            boost: None,
74            _name: None,
75        }
76    }
77}
78
79impl ShapeLookupQuery {
80    /// Name of the index where the pre-indexed shape is. Defaults to shapes
81    pub fn index<S>(mut self, index: S) -> Self
82    where
83        S: ToString,
84    {
85        self.shape.indexed_shape.index = Some(index.to_string());
86        self
87    }
88
89    /// The field specified as path containing the pre-indexed shape. Defaults to shape
90    pub fn path<S>(mut self, path: S) -> Self
91    where
92        S: ToString,
93    {
94        self.shape.indexed_shape.path = Some(path.to_string());
95        self
96    }
97
98    /// The routing of the shape document
99    pub fn routing<S>(mut self, routing: S) -> Self
100    where
101        S: ToString,
102    {
103        self.shape.indexed_shape.routing = Some(routing.to_string());
104        self
105    }
106
107    /// The [shape strategy](https://www.elastic.co/guide/en/elasticsearch/reference/current/geo-shape.html#spatial-strategy)
108    /// mapping parameter determines which spatial relation operators may be
109    /// used at search time.
110    pub fn relation(mut self, relation: SpatialRelation) -> Self {
111        self.shape.relation = Some(relation);
112        self
113    }
114
115    /// When set to true the `ignore_unmapped` option will ignore an unmapped
116    /// field and will not match any documents for this query. This can be
117    /// useful when querying multiple indexes which might have different
118    /// mappings. When set to `false` (the default value) the query will throw
119    /// an exception if the field is not mapped.
120    pub fn ignore_unmapped(mut self, ignore_unmapped: bool) -> Self {
121        self.ignore_unmapped = Some(ignore_unmapped);
122        self
123    }
124
125    add_boost_and_name!();
126}
127
128impl ShouldSkip for ShapeLookupQuery {}
129
130serialize_with_root_key_value_pair!("shape": ShapeLookupQuery, field, shape);
131
132#[cfg(test)]
133mod tests {
134    use super::*;
135
136    #[test]
137    fn test_serialization() {
138        assert_serialize_query(
139            Query::shape_lookup("pin.location", "id"),
140            json!({
141                "shape": {
142                    "pin.location": {
143                        "indexed_shape": {
144                            "id": "id",
145                        }
146                    },
147                }
148            }),
149        );
150
151        assert_serialize_query(
152            Query::shape_lookup("pin.location", "id")
153                .boost(2)
154                .name("test")
155                .ignore_unmapped(true)
156                .relation(SpatialRelation::Within)
157                .routing("routing")
158                .index("index")
159                .path("path"),
160            json!({
161                "shape": {
162                    "_name": "test",
163                    "boost": 2.0,
164                    "ignore_unmapped": true,
165                    "pin.location": {
166                        "indexed_shape": {
167                            "id": "id",
168                            "index": "index",
169                            "path": "path",
170                            "routing": "routing"
171                        },
172                        "relation": "WITHIN"
173                    },
174                }
175            }),
176        );
177    }
178}