use std::fmt::Debug;
use chrono::{DateTime, Utc};
use serde::{de::DeserializeOwned, ser::Serialize};
use crate::{search::*, util::*};
#[doc(hidden)]
pub trait Origin: Debug + PartialEq + DeserializeOwned + Serialize + Clone {
type Pivot: Debug + PartialEq + DeserializeOwned + Serialize + Clone;
}
impl Origin for DateTime<Utc> {
type Pivot = Time;
}
impl Origin for GeoLocation {
type Pivot = Distance;
}
#[derive(Debug, Clone, PartialEq, Serialize)]
#[serde(remote = "Self")]
pub struct DistanceFeatureQuery<O>
where
O: Origin + DeserializeOwned,
{
field: String,
origin: O,
pivot: <O as Origin>::Pivot,
#[serde(default, skip_serializing_if = "ShouldSkip::should_skip")]
boost: Option<f32>,
#[serde(default, skip_serializing_if = "ShouldSkip::should_skip")]
_name: Option<String>,
}
impl Query {
pub fn distance_feature<T, O>(
field: T,
origin: O,
pivot: <O as Origin>::Pivot,
) -> DistanceFeatureQuery<O>
where
T: ToString,
O: Origin,
{
DistanceFeatureQuery {
field: field.to_string(),
origin,
pivot,
boost: None,
_name: None,
}
}
}
impl<O> DistanceFeatureQuery<O>
where
O: Origin,
{
add_boost_and_name!();
}
impl<O> ShouldSkip for DistanceFeatureQuery<O> where O: Origin {}
serialize_with_root!("distance_feature": DistanceFeatureQuery<DateTime<Utc>>);
deserialize_with_root!("distance_feature": DistanceFeatureQuery<DateTime<Utc>>);
serialize_with_root!("distance_feature": DistanceFeatureQuery<GeoLocation>);
deserialize_with_root!("distance_feature": DistanceFeatureQuery<GeoLocation>);
#[cfg(test)]
mod tests {
use chrono::prelude::*;
use super::*;
#[test]
fn serialization() {
assert_serialize_query(
Query::distance_feature(
"test",
Utc.with_ymd_and_hms(2014, 7, 8, 9, 1, 0).single().unwrap(),
Time::Days(7),
),
json!({
"distance_feature": {
"field": "test",
"origin": "2014-07-08T09:01:00Z",
"pivot": "7d",
}
}),
);
assert_serialize_query(
Query::distance_feature(
"test",
Utc.with_ymd_and_hms(2014, 7, 8, 9, 1, 0).single().unwrap(),
Time::Days(7),
)
.boost(1.5)
.name("test"),
json!({
"distance_feature": {
"field": "test",
"origin": "2014-07-08T09:01:00Z",
"pivot": "7d",
"boost": 1.5,
"_name": "test",
}
}),
);
assert_serialize_query(
Query::distance_feature(
"test",
GeoLocation::new(12.0, 13.0),
Distance::Kilometers(15),
),
json!({
"distance_feature": {
"field": "test",
"origin": [13.0, 12.0],
"pivot": "15km",
}
}),
);
assert_serialize_query(
Query::distance_feature(
"test",
GeoLocation::new(12.0, 13.0),
Distance::Kilometers(15),
)
.boost(2)
.name("test"),
json!({
"distance_feature": {
"field": "test",
"origin": [13.0, 12.0],
"pivot": "15km",
"boost": 2.0,
"_name": "test",
}
}),
);
}
}