use serde::Serialize;
use crate::{search::*, util::*};
#[derive(Debug, Clone, PartialEq, Deserialize, Serialize)]
#[serde(remote = "Self")]
pub struct RangeQuery {
#[serde(skip)]
field: String,
#[serde(default, skip_serializing_if = "ShouldSkip::should_skip")]
gt: Option<Term>,
#[serde(default, skip_serializing_if = "ShouldSkip::should_skip")]
gte: Option<Term>,
#[serde(default, skip_serializing_if = "ShouldSkip::should_skip")]
lt: Option<Term>,
#[serde(default, skip_serializing_if = "ShouldSkip::should_skip")]
lte: Option<Term>,
#[serde(default, skip_serializing_if = "ShouldSkip::should_skip")]
format: Option<String>,
#[serde(default, skip_serializing_if = "ShouldSkip::should_skip")]
relation: Option<RangeRelation>,
#[serde(default, skip_serializing_if = "ShouldSkip::should_skip")]
time_zone: Option<String>,
#[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 range<T>(field: T) -> RangeQuery
where
T: ToString,
{
RangeQuery {
field: field.to_string(),
gt: Default::default(),
gte: Default::default(),
lt: Default::default(),
lte: Default::default(),
format: None,
relation: None,
time_zone: None,
boost: None,
_name: None,
}
}
}
impl RangeQuery {
add_boost_and_name!();
pub fn gt<T>(mut self, gt: T) -> Self
where
T: Serialize,
{
self.gt = Term::new(gt);
self
}
pub fn gte<T>(mut self, gte: T) -> Self
where
T: Serialize,
{
self.gte = Term::new(gte);
self
}
pub fn lt<T>(mut self, lt: T) -> Self
where
T: Serialize,
{
self.lt = Term::new(lt);
self
}
pub fn lte<T>(mut self, lte: T) -> Self
where
T: Serialize,
{
self.lte = Term::new(lte);
self
}
pub fn format<T>(mut self, format: T) -> Self
where
T: ToString,
{
self.format = Some(format.to_string());
self
}
pub fn relation(mut self, relation: RangeRelation) -> Self {
self.relation = Some(relation);
self
}
pub fn time_zone<T>(mut self, time_zone: T) -> Self
where
T: ToString,
{
self.time_zone = Some(time_zone.to_string());
self
}
}
impl ShouldSkip for RangeQuery {
fn should_skip(&self) -> bool {
self.gt.should_skip()
&& self.gte.should_skip()
&& self.lt.should_skip()
&& self.lte.should_skip()
}
}
serialize_with_root_keyed!("range": RangeQuery);
deserialize_with_root_keyed!("range": RangeQuery);
#[cfg(test)]
mod tests {
use chrono::prelude::*;
use super::*;
#[test]
fn serialization() {
assert_serialize_query(
Query::range("test_field"),
json!({
"range": {
"test_field": {}
}
}),
);
assert_serialize_query(
Query::range("test_field")
.gt(None::<i32>)
.lt(None::<i32>)
.gte(None::<i32>)
.lte(None::<i32>),
json!({
"range": {
"test_field": {}
}
}),
);
assert_serialize_query(
Query::range("test_numeric_field")
.gt(1)
.gte(2)
.lt(3)
.lte(4)
.relation(RangeRelation::Within)
.boost(2)
.name("range_query_test"),
json!({
"range": {
"test_numeric_field": {
"gt": 1,
"gte": 2,
"lt": 3,
"lte": 4,
"relation": "WITHIN",
"boost": 2.0,
"_name": "range_query_test"
}
}
}),
);
assert_serialize_query(
Query::range("test_date_field")
.gt(Utc
.with_ymd_and_hms(2014, 11, 28, 12, 0, 1)
.single()
.unwrap())
.gte(
Utc.with_ymd_and_hms(2014, 11, 28, 12, 0, 2)
.single()
.unwrap(),
)
.lt(Utc
.with_ymd_and_hms(2014, 11, 28, 12, 0, 3)
.single()
.unwrap())
.lte(
Utc.with_ymd_and_hms(2014, 11, 28, 12, 0, 4)
.single()
.unwrap(),
)
.relation(RangeRelation::Contains)
.format("yyyy-MM-dd")
.time_zone("UTC")
.boost(2)
.name("range_query_test"),
json!({
"range": {
"test_date_field": {
"gt": "2014-11-28T12:00:01Z",
"gte": "2014-11-28T12:00:02Z",
"lt": "2014-11-28T12:00:03Z",
"lte": "2014-11-28T12:00:04Z",
"format": "yyyy-MM-dd",
"time_zone": "UTC",
"relation": "CONTAINS",
"boost": 2.0,
"_name": "range_query_test"
}
}
}),
);
}
}