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
use crate::search::*;
use crate::util::*;
use serde::Serialize;
/// Queries documents that contain fields indexed using the `shape` type.
///
/// Requires the [`shape` Mapping](https://www.elastic.co/guide/en/elasticsearch/reference/current/shape.html).
///
/// <https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-shape-query.html>
#[derive(Debug, Clone, PartialEq, Serialize)]
#[serde(remote = "Self")]
pub struct ShapeQuery {
#[serde(skip)]
field: String,
#[serde(skip)]
shape: InlineShape,
#[serde(skip_serializing_if = "ShouldSkip::should_skip")]
ignore_unmapped: Option<bool>,
#[serde(skip_serializing_if = "ShouldSkip::should_skip")]
boost: Option<f32>,
#[serde(skip_serializing_if = "ShouldSkip::should_skip")]
_name: Option<String>,
}
#[derive(Debug, Clone, PartialEq, Serialize)]
struct InlineShape {
shape: Shape,
#[serde(skip_serializing_if = "ShouldSkip::should_skip")]
relation: Option<SpatialRelation>,
}
impl Query {
/// Creates an instance of [`ShapeQuery`]
///
/// - `field` - Field you wish to search
/// - `shape` - Shape you with to search
pub fn shape<S, T>(field: S, shape: T) -> ShapeQuery
where
S: ToString,
T: Into<Shape>,
{
ShapeQuery {
field: field.to_string(),
shape: InlineShape {
shape: shape.into(),
relation: None,
},
ignore_unmapped: None,
boost: None,
_name: None,
}
}
}
impl ShapeQuery {
/// The [shape strategy](https://www.elastic.co/guide/en/elasticsearch/reference/current/geo-shape.html#spatial-strategy)
/// mapping parameter determines which spatial relation operators may be
/// used at search time.
pub fn relation(mut self, relation: SpatialRelation) -> Self {
self.shape.relation = Some(relation);
self
}
/// When set to true the `ignore_unmapped` option will ignore an unmapped
/// field and will not match any documents for this query. This can be
/// useful when querying multiple indexes which might have different
/// mappings. When set to `false` (the default value) the query will throw
/// an exception if the field is not mapped.
pub fn ignore_unmapped(mut self, ignore_unmapped: bool) -> Self {
self.ignore_unmapped = Some(ignore_unmapped);
self
}
add_boost_and_name!();
}
impl ShouldSkip for ShapeQuery {}
serialize_with_root_key_value_pair!("shape": ShapeQuery, field, shape);
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_serialization() {
assert_serialize_query(
Query::shape("pin.location", Shape::point([2.2, 1.1])),
json!({
"shape": {
"pin.location": {
"shape": {
"type": "point",
"coordinates": [2.2, 1.1]
}
},
}
}),
);
assert_serialize_query(
Query::shape("pin.location", Shape::point([2.2, 1.1]))
.boost(2)
.name("test")
.ignore_unmapped(true)
.relation(SpatialRelation::Within),
json!({
"shape": {
"_name": "test",
"boost": 2.0,
"ignore_unmapped": true,
"pin.location": {
"shape": {
"type": "point",
"coordinates": [2.2, 1.1]
},
"relation": "WITHIN"
},
}
}),
);
}
}