use serde::Serialize;
use serde_json::Value;
#[derive(Debug, Clone, Serialize)]
pub struct Query {
method: String,
#[serde(skip_serializing_if = "Option::is_none")]
attribute: Option<String>,
#[serde(skip_serializing_if = "Vec::is_empty")]
values: Vec<Value>,
}
impl Query {
fn new(method: String, attribute: Option<String>, values: Vec<Value>) -> Self {
Self {
method,
attribute,
values,
}
}
fn to_array(value: Value) -> Vec<Value> {
match value {
Value::Array(arr) => arr,
_ => vec![value],
}
}
pub fn equal<S: Into<String>, V: Into<Value>>(attribute: S, value: V) -> Self {
Self::new("equal".to_string(), Some(attribute.into()), Self::to_array(value.into()))
}
pub fn not_equal<S: Into<String>, V: Into<Value>>(attribute: S, value: V) -> Self {
Self::new("notEqual".to_string(), Some(attribute.into()), Self::to_array(value.into()))
}
pub fn less_than<S: Into<String>, V: Into<Value>>(attribute: S, value: V) -> Self {
Self::new("lessThan".to_string(), Some(attribute.into()), Self::to_array(value.into()))
}
pub fn less_than_equal<S: Into<String>, V: Into<Value>>(attribute: S, value: V) -> Self {
Self::new("lessThanEqual".to_string(), Some(attribute.into()), Self::to_array(value.into()))
}
pub fn greater_than<S: Into<String>, V: Into<Value>>(attribute: S, value: V) -> Self {
Self::new("greaterThan".to_string(), Some(attribute.into()), Self::to_array(value.into()))
}
pub fn greater_than_equal<S: Into<String>, V: Into<Value>>(attribute: S, value: V) -> Self {
Self::new("greaterThanEqual".to_string(), Some(attribute.into()), Self::to_array(value.into()))
}
pub fn is_null<S: Into<String>>(attribute: S) -> Self {
Self::new("isNull".to_string(), Some(attribute.into()), vec![])
}
pub fn is_not_null<S: Into<String>>(attribute: S) -> Self {
Self::new("isNotNull".to_string(), Some(attribute.into()), vec![])
}
pub fn between<S: Into<String>, V: Into<Value>>(attribute: S, start: V, end: V) -> Self {
Self::new("between".to_string(), Some(attribute.into()), vec![start.into(), end.into()])
}
pub fn starts_with<S: Into<String>, V: Into<Value>>(attribute: S, value: V) -> Self {
Self::new("startsWith".to_string(), Some(attribute.into()), Self::to_array(value.into()))
}
pub fn ends_with<S: Into<String>, V: Into<Value>>(attribute: S, value: V) -> Self {
Self::new("endsWith".to_string(), Some(attribute.into()), Self::to_array(value.into()))
}
pub fn select<I: IntoIterator<Item = S>, S: Into<String>>(attributes: I) -> Self {
let values: Vec<Value> = attributes.into_iter().map(|s| Value::String(s.into())).collect();
Self::new("select".to_string(), None, values)
}
pub fn search<S: Into<String>, V: Into<Value>>(attribute: S, value: V) -> Self {
Self::new("search".to_string(), Some(attribute.into()), Self::to_array(value.into()))
}
pub fn not_search<S: Into<String>, V: Into<Value>>(attribute: S, value: V) -> Self {
Self::new("notSearch".to_string(), Some(attribute.into()), Self::to_array(value.into()))
}
pub fn order_asc<S: Into<String>>(attribute: S) -> Self {
Self::new("orderAsc".to_string(), Some(attribute.into()), vec![])
}
pub fn order_desc<S: Into<String>>(attribute: S) -> Self {
Self::new("orderDesc".to_string(), Some(attribute.into()), vec![])
}
pub fn order_random() -> Self {
Self::new("orderRandom".to_string(), None, vec![])
}
pub fn cursor_after<S: Into<String>>(document_id: S) -> Self {
Self::new("cursorAfter".to_string(), None, vec![Value::String(document_id.into())])
}
pub fn cursor_before<S: Into<String>>(document_id: S) -> Self {
Self::new("cursorBefore".to_string(), None, vec![Value::String(document_id.into())])
}
pub fn limit(value: u32) -> Self {
Self::new("limit".to_string(), None, vec![Value::Number(value.into())])
}
pub fn offset(value: u32) -> Self {
Self::new("offset".to_string(), None, vec![Value::Number(value.into())])
}
pub fn contains<S: Into<String>, V: Into<Value>>(attribute: S, value: V) -> Self {
Self::new("contains".to_string(), Some(attribute.into()), Self::to_array(value.into()))
}
pub fn contains_any<S: Into<String>, V: Into<Value>>(attribute: S, values: Vec<V>) -> Self {
Self::new("containsAny".to_string(), Some(attribute.into()), values.into_iter().map(|v| v.into()).collect())
}
pub fn contains_all<S: Into<String>, V: Into<Value>>(attribute: S, values: Vec<V>) -> Self {
Self::new("containsAll".to_string(), Some(attribute.into()), values.into_iter().map(|v| v.into()).collect())
}
pub fn not_contains<S: Into<String>, V: Into<Value>>(attribute: S, value: V) -> Self {
Self::new("notContains".to_string(), Some(attribute.into()), Self::to_array(value.into()))
}
pub fn not_between<S: Into<String>, V: Into<Value>>(attribute: S, start: V, end: V) -> Self {
Self::new("notBetween".to_string(), Some(attribute.into()), vec![start.into(), end.into()])
}
pub fn not_starts_with<S: Into<String>, V: Into<Value>>(attribute: S, value: V) -> Self {
Self::new("notStartsWith".to_string(), Some(attribute.into()), Self::to_array(value.into()))
}
pub fn not_ends_with<S: Into<String>, V: Into<Value>>(attribute: S, value: V) -> Self {
Self::new("notEndsWith".to_string(), Some(attribute.into()), Self::to_array(value.into()))
}
pub fn created_before<V: Into<Value>>(value: V) -> Self {
Self::less_than("$createdAt", value)
}
pub fn created_after<V: Into<Value>>(value: V) -> Self {
Self::greater_than("$createdAt", value)
}
pub fn created_between<V: Into<Value>>(start: V, end: V) -> Self {
Self::between("$createdAt", start, end)
}
pub fn updated_before<V: Into<Value>>(value: V) -> Self {
Self::less_than("$updatedAt", value)
}
pub fn updated_after<V: Into<Value>>(value: V) -> Self {
Self::greater_than("$updatedAt", value)
}
pub fn updated_between<V: Into<Value>>(start: V, end: V) -> Self {
Self::between("$updatedAt", start, end)
}
pub fn distance_equal<S: Into<String>, V: Into<Value>>(attribute: S, values: V, distance: impl Into<Value>, meters: bool) -> Self {
let params = Value::Array(vec![values.into(), distance.into(), Value::Bool(meters)]);
Self::new("distanceEqual".to_string(), Some(attribute.into()), vec![params])
}
pub fn distance_not_equal<S: Into<String>, V: Into<Value>>(attribute: S, values: V, distance: impl Into<Value>, meters: bool) -> Self {
let params = Value::Array(vec![values.into(), distance.into(), Value::Bool(meters)]);
Self::new("distanceNotEqual".to_string(), Some(attribute.into()), vec![params])
}
pub fn distance_greater_than<S: Into<String>, V: Into<Value>>(attribute: S, values: V, distance: impl Into<Value>, meters: bool) -> Self {
let params = Value::Array(vec![values.into(), distance.into(), Value::Bool(meters)]);
Self::new("distanceGreaterThan".to_string(), Some(attribute.into()), vec![params])
}
pub fn distance_less_than<S: Into<String>, V: Into<Value>>(attribute: S, values: V, distance: impl Into<Value>, meters: bool) -> Self {
let params = Value::Array(vec![values.into(), distance.into(), Value::Bool(meters)]);
Self::new("distanceLessThan".to_string(), Some(attribute.into()), vec![params])
}
pub fn intersects<S: Into<String>, V: Into<Value>>(attribute: S, values: V) -> Self {
Self::new("intersects".to_string(), Some(attribute.into()), vec![values.into()])
}
pub fn not_intersects<S: Into<String>, V: Into<Value>>(attribute: S, values: V) -> Self {
Self::new("notIntersects".to_string(), Some(attribute.into()), vec![values.into()])
}
pub fn crosses<S: Into<String>, V: Into<Value>>(attribute: S, values: V) -> Self {
Self::new("crosses".to_string(), Some(attribute.into()), vec![values.into()])
}
pub fn not_crosses<S: Into<String>, V: Into<Value>>(attribute: S, values: V) -> Self {
Self::new("notCrosses".to_string(), Some(attribute.into()), vec![values.into()])
}
pub fn overlaps<S: Into<String>, V: Into<Value>>(attribute: S, values: V) -> Self {
Self::new("overlaps".to_string(), Some(attribute.into()), vec![values.into()])
}
pub fn not_overlaps<S: Into<String>, V: Into<Value>>(attribute: S, values: V) -> Self {
Self::new("notOverlaps".to_string(), Some(attribute.into()), vec![values.into()])
}
pub fn touches<S: Into<String>, V: Into<Value>>(attribute: S, values: V) -> Self {
Self::new("touches".to_string(), Some(attribute.into()), vec![values.into()])
}
pub fn not_touches<S: Into<String>, V: Into<Value>>(attribute: S, values: V) -> Self {
Self::new("notTouches".to_string(), Some(attribute.into()), vec![values.into()])
}
pub fn or<I, S>(queries: I) -> Self
where
I: IntoIterator<Item = S>,
S: AsRef<str>,
{
let values: Vec<Value> = queries
.into_iter()
.filter_map(|query| serde_json::from_str(query.as_ref()).ok())
.collect();
Self::new("or".to_string(), None, values)
}
pub fn and<I, S>(queries: I) -> Self
where
I: IntoIterator<Item = S>,
S: AsRef<str>,
{
let values: Vec<Value> = queries
.into_iter()
.filter_map(|query| serde_json::from_str(query.as_ref()).ok())
.collect();
Self::new("and".to_string(), None, values)
}
pub fn regex<S: Into<String>, V: Into<Value>>(attribute: S, value: V) -> Self {
Self::new("regex".to_string(), Some(attribute.into()), Self::to_array(value.into()))
}
pub fn exists<V: Into<Value>>(attributes: Vec<V>) -> Self {
Self::new("exists".to_string(), None, attributes.into_iter().map(|v| v.into()).collect())
}
pub fn not_exists<V: Into<Value>>(attributes: Vec<V>) -> Self {
Self::new("notExists".to_string(), None, attributes.into_iter().map(|v| v.into()).collect())
}
pub fn elem_match<S, I, Q>(attribute: S, queries: I) -> Self
where
S: Into<String>,
I: IntoIterator<Item = Q>,
Q: AsRef<str>,
{
let values: Vec<Value> = queries
.into_iter()
.filter_map(|query| serde_json::from_str(query.as_ref()).ok())
.collect();
Self::new("elemMatch".to_string(), Some(attribute.into()), values)
}
pub fn to_value(self) -> Value {
let mut obj = serde_json::Map::new();
obj.insert("method".to_string(), Value::String(self.method));
if let Some(attr) = self.attribute {
obj.insert("attribute".to_string(), Value::String(attr));
}
if !self.values.is_empty() {
obj.insert("values".to_string(), Value::Array(self.values));
}
Value::Object(obj)
}
}
impl std::fmt::Display for Query {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let json_str = serde_json::to_string(self)
.unwrap_or_else(|_| String::new());
write!(f, "{}", json_str)
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_equal_query() {
let query = Query::equal("name", "John");
let value = query.to_value();
assert_eq!(value["method"], "equal");
assert_eq!(value["attribute"], "name");
assert_eq!(value["values"][0], "John");
}
#[test]
fn test_greater_than_query() {
let query = Query::greater_than("age", 18);
let value = query.to_value();
assert_eq!(value["method"], "greaterThan");
assert_eq!(value["attribute"], "age");
assert_eq!(value["values"][0], 18);
}
#[test]
fn test_between_query() {
let query = Query::between("age", 18, 65);
let value = query.to_value();
assert_eq!(value["method"], "between");
assert_eq!(value["attribute"], "age");
assert_eq!(value["values"][0], 18);
assert_eq!(value["values"][1], 65);
}
#[test]
fn test_select_query() {
let query = Query::select(vec!["name", "age"]);
let value = query.to_value();
assert_eq!(value["method"], "select");
assert_eq!(value["values"][0], "name");
assert_eq!(value["values"][1], "age");
}
#[test]
fn test_order_asc_query() {
let query = Query::order_asc("name");
let value = query.to_value();
assert_eq!(value["method"], "orderAsc");
assert_eq!(value["attribute"], "name");
}
#[test]
fn test_limit_query() {
let query = Query::limit(10);
let value = query.to_value();
assert_eq!(value["method"], "limit");
assert_eq!(value["values"][0], 10);
}
#[test]
fn test_or_query() {
let query_strings = vec![
Query::equal("released", true).to_string(),
Query::less_than("releasedYear", 1990).to_string(),
];
let query = Query::or(query_strings);
let value = query.to_value();
assert_eq!(value["method"], "or");
assert!(value["values"].is_array());
assert_eq!(value["values"].as_array().unwrap().len(), 2);
}
#[test]
fn test_and_query() {
let query_strings = vec![
Query::equal("released", false).to_string(),
Query::greater_than("releasedYear", 2015).to_string(),
];
let query = Query::and(query_strings);
let value = query.to_value();
assert_eq!(value["method"], "and");
assert!(value["values"].is_array());
assert_eq!(value["values"].as_array().unwrap().len(), 2);
}
#[test]
fn test_or_invalid_json_skipped() {
let mixed_queries = vec![
Query::equal("released", true).to_string(),
"not valid json".to_string(),
Query::less_than("releasedYear", 1990).to_string(),
];
let query = Query::or(mixed_queries);
let value = query.to_value();
assert_eq!(value["method"], "or");
assert_eq!(value["values"].as_array().unwrap().len(), 2);
}
#[test]
fn test_and_invalid_json_skipped() {
let mixed_queries = vec![
"not valid json".to_string(),
Query::greater_than("releasedYear", 2015).to_string(),
];
let query = Query::and(mixed_queries);
let value = query.to_value();
assert_eq!(value["method"], "and");
assert_eq!(value["values"].as_array().unwrap().len(), 1);
}
#[test]
fn test_json_serialization() {
let query = Query::equal("name", "John");
let json_str = query.to_string();
let parsed: Value = serde_json::from_str(&json_str).unwrap();
assert_eq!(parsed["method"], "equal");
assert_eq!(parsed["attribute"], "name");
assert_eq!(parsed["values"][0], "John");
}
#[test]
fn test_equal_with_array() {
let arr = vec!["Movie1", "Movie2"];
let query = Query::equal("title", Value::Array(arr.iter().map(|s| Value::String(s.to_string())).collect()));
let value = query.to_value();
assert_eq!(value["method"], "equal");
assert_eq!(value["attribute"], "title");
assert_eq!(value["values"].as_array().unwrap().len(), 2);
assert_eq!(value["values"][0], "Movie1");
assert_eq!(value["values"][1], "Movie2");
}
#[test]
fn test_not_equal() {
let query = Query::not_equal("status", "draft");
let value = query.to_value();
assert_eq!(value["method"], "notEqual");
assert_eq!(value["attribute"], "status");
assert_eq!(value["values"][0], "draft");
}
#[test]
fn test_less_than() {
let query = Query::less_than("age", 18);
let value = query.to_value();
assert_eq!(value["method"], "lessThan");
assert_eq!(value["attribute"], "age");
assert_eq!(value["values"][0], 18);
}
#[test]
fn test_less_than_equal() {
let query = Query::less_than_equal("score", 100);
let value = query.to_value();
assert_eq!(value["method"], "lessThanEqual");
assert_eq!(value["attribute"], "score");
assert_eq!(value["values"][0], 100);
}
#[test]
fn test_greater_than_equal() {
let query = Query::greater_than_equal("age", 21);
let value = query.to_value();
assert_eq!(value["method"], "greaterThanEqual");
assert_eq!(value["attribute"], "age");
assert_eq!(value["values"][0], 21);
}
#[test]
fn test_search() {
let query = Query::search("content", "keyword1 keyword2");
let value = query.to_value();
assert_eq!(value["method"], "search");
assert_eq!(value["attribute"], "content");
assert_eq!(value["values"][0], "keyword1 keyword2");
}
#[test]
fn test_search_with_number() {
let query = Query::search("age", 42);
let value = query.to_value();
assert_eq!(value["method"], "search");
assert_eq!(value["attribute"], "age");
assert_eq!(value["values"][0], 42);
}
#[test]
fn test_is_null() {
let query = Query::is_null("deletedAt");
let value = query.to_value();
assert_eq!(value["method"], "isNull");
assert_eq!(value["attribute"], "deletedAt");
}
#[test]
fn test_is_not_null() {
let query = Query::is_not_null("publishedAt");
let value = query.to_value();
assert_eq!(value["method"], "isNotNull");
assert_eq!(value["attribute"], "publishedAt");
}
#[test]
fn test_contains() {
let query = Query::contains("tags", "rust");
let value = query.to_value();
assert_eq!(value["method"], "contains");
assert_eq!(value["attribute"], "tags");
assert_eq!(value["values"][0], "rust");
}
#[test]
fn test_not_contains() {
let query = Query::not_contains("tags", "rust");
let value = query.to_value();
assert_eq!(value["method"], "notContains");
assert_eq!(value["attribute"], "tags");
assert_eq!(value["values"][0], "rust");
}
#[test]
fn test_not_search_with_number() {
let query = Query::not_search("age", 7);
let value = query.to_value();
assert_eq!(value["method"], "notSearch");
assert_eq!(value["attribute"], "age");
assert_eq!(value["values"][0], 7);
}
#[test]
fn test_not_search_with_array() {
let values = Value::Array(vec![Value::from("x"), Value::from("y")]);
let query = Query::not_search("tags", values);
let value = query.to_value();
assert_eq!(value["method"], "notSearch");
assert_eq!(value["attribute"], "tags");
assert_eq!(value["values"][0], "x");
assert_eq!(value["values"][1], "y");
}
#[test]
fn test_starts_with() {
let query = Query::starts_with("name", "John");
let value = query.to_value();
assert_eq!(value["method"], "startsWith");
assert_eq!(value["attribute"], "name");
assert_eq!(value["values"][0], "John");
}
#[test]
fn test_starts_with_with_bool() {
let query = Query::starts_with("active", true);
let value = query.to_value();
assert_eq!(value["method"], "startsWith");
assert_eq!(value["attribute"], "active");
assert_eq!(value["values"][0], true);
}
#[test]
fn test_not_starts_with_with_bool() {
let query = Query::not_starts_with("active", false);
let value = query.to_value();
assert_eq!(value["method"], "notStartsWith");
assert_eq!(value["attribute"], "active");
assert_eq!(value["values"][0], false);
}
#[test]
fn test_ends_with() {
let query = Query::ends_with("email", "@example.com");
let value = query.to_value();
assert_eq!(value["method"], "endsWith");
assert_eq!(value["attribute"], "email");
assert_eq!(value["values"][0], "@example.com");
}
#[test]
fn test_ends_with_with_array() {
let values = Value::Array(vec![Value::from("a"), Value::from("b")]);
let query = Query::ends_with("tags", values);
let value = query.to_value();
assert_eq!(value["method"], "endsWith");
assert_eq!(value["attribute"], "tags");
assert_eq!(value["values"][0], "a");
assert_eq!(value["values"][1], "b");
}
#[test]
fn test_not_ends_with_with_array() {
let values = Value::Array(vec![Value::from("x"), Value::from("y")]);
let query = Query::not_ends_with("tags", values);
let value = query.to_value();
assert_eq!(value["method"], "notEndsWith");
assert_eq!(value["attribute"], "tags");
assert_eq!(value["values"][0], "x");
assert_eq!(value["values"][1], "y");
}
#[test]
fn test_order_desc() {
let query = Query::order_desc("createdAt");
let value = query.to_value();
assert_eq!(value["method"], "orderDesc");
assert_eq!(value["attribute"], "createdAt");
}
#[test]
fn test_order_random() {
let query = Query::order_random();
let value = query.to_value();
assert_eq!(value["method"], "orderRandom");
}
#[test]
fn test_cursor_before() {
let query = Query::cursor_before("doc123");
let value = query.to_value();
assert_eq!(value["method"], "cursorBefore");
assert_eq!(value["values"][0], "doc123");
}
#[test]
fn test_cursor_after() {
let query = Query::cursor_after("doc456");
let value = query.to_value();
assert_eq!(value["method"], "cursorAfter");
assert_eq!(value["values"][0], "doc456");
}
#[test]
fn test_offset() {
let query = Query::offset(50);
let value = query.to_value();
assert_eq!(value["method"], "offset");
assert_eq!(value["values"][0], 50);
}
#[test]
fn test_distance_equal() {
let query = Query::distance_equal("location", Value::Array(vec![Value::from(40.7128), Value::from(-74.0060)]), 5000, true);
let value = query.to_value();
assert_eq!(value["method"], "distanceEqual");
assert_eq!(value["attribute"], "location");
let params = value["values"][0].as_array().unwrap();
assert_eq!(params[1], 5000);
assert_eq!(params[2], true);
}
#[test]
fn test_distance_not_equal() {
let query = Query::distance_not_equal("location", Value::Array(vec![Value::from(40.7128), Value::from(-74.0060)]), 5000, false);
let value = query.to_value();
assert_eq!(value["method"], "distanceNotEqual");
assert_eq!(value["attribute"], "location");
let params = value["values"][0].as_array().unwrap();
assert_eq!(params[1], 5000);
assert_eq!(params[2], false);
}
#[test]
fn test_distance_greater_than() {
let query = Query::distance_greater_than("location", Value::Array(vec![Value::from(1.0), Value::from(2.0)]), 123, true);
let value = query.to_value();
assert_eq!(value["method"], "distanceGreaterThan");
assert_eq!(value["attribute"], "location");
let params = value["values"][0].as_array().unwrap();
assert_eq!(params[1], 123);
assert_eq!(params[2], true);
}
#[test]
fn test_distance_less_than() {
let query = Query::distance_less_than("location", Value::Array(vec![Value::from(1.0), Value::from(2.0)]), 321, false);
let value = query.to_value();
assert_eq!(value["method"], "distanceLessThan");
assert_eq!(value["attribute"], "location");
let params = value["values"][0].as_array().unwrap();
assert_eq!(params[1], 321);
assert_eq!(params[2], false);
}
#[test]
fn test_intersects() {
let query = Query::intersects("geo", Value::Array(vec![Value::from(1), Value::from(2)]));
let value = query.to_value();
assert_eq!(value["method"], "intersects");
assert_eq!(value["attribute"], "geo");
assert_eq!(value["values"][0][0], 1);
assert_eq!(value["values"][0][1], 2);
}
#[test]
fn test_not_intersects() {
let query = Query::not_intersects("geo", Value::Array(vec![Value::from(1), Value::from(2)]));
let value = query.to_value();
assert_eq!(value["method"], "notIntersects");
assert_eq!(value["attribute"], "geo");
assert_eq!(value["values"][0][0], 1);
assert_eq!(value["values"][0][1], 2);
}
#[test]
fn test_crosses() {
let query = Query::crosses("geo", Value::Array(vec![Value::from(1), Value::from(2)]));
let value = query.to_value();
assert_eq!(value["method"], "crosses");
assert_eq!(value["attribute"], "geo");
assert_eq!(value["values"][0][0], 1);
assert_eq!(value["values"][0][1], 2);
}
#[test]
fn test_not_crosses() {
let query = Query::not_crosses("geo", Value::Array(vec![Value::from(1), Value::from(2)]));
let value = query.to_value();
assert_eq!(value["method"], "notCrosses");
assert_eq!(value["attribute"], "geo");
assert_eq!(value["values"][0][0], 1);
assert_eq!(value["values"][0][1], 2);
}
#[test]
fn test_overlaps() {
let query = Query::overlaps("geo", Value::Array(vec![Value::from(1), Value::from(2)]));
let value = query.to_value();
assert_eq!(value["method"], "overlaps");
assert_eq!(value["attribute"], "geo");
assert_eq!(value["values"][0][0], 1);
assert_eq!(value["values"][0][1], 2);
}
#[test]
fn test_not_overlaps() {
let query = Query::not_overlaps("geo", Value::Array(vec![Value::from(1), Value::from(2)]));
let value = query.to_value();
assert_eq!(value["method"], "notOverlaps");
assert_eq!(value["attribute"], "geo");
assert_eq!(value["values"][0][0], 1);
assert_eq!(value["values"][0][1], 2);
}
#[test]
fn test_touches() {
let query = Query::touches("geo", Value::Array(vec![Value::from(1), Value::from(2)]));
let value = query.to_value();
assert_eq!(value["method"], "touches");
assert_eq!(value["attribute"], "geo");
assert_eq!(value["values"][0][0], 1);
assert_eq!(value["values"][0][1], 2);
}
#[test]
fn test_not_touches() {
let query = Query::not_touches("geo", Value::Array(vec![Value::from(1), Value::from(2)]));
let value = query.to_value();
assert_eq!(value["method"], "notTouches");
assert_eq!(value["attribute"], "geo");
assert_eq!(value["values"][0][0], 1);
assert_eq!(value["values"][0][1], 2);
}
#[test]
fn test_not_between() {
let query = Query::not_between("age", 18, 30);
let value = query.to_value();
assert_eq!(value["method"], "notBetween");
assert_eq!(value["attribute"], "age");
assert_eq!(value["values"][0], 18);
assert_eq!(value["values"][1], 30);
}
#[test]
fn test_not_starts_with() {
let query = Query::not_starts_with("name", "Ann");
let value = query.to_value();
assert_eq!(value["method"], "notStartsWith");
assert_eq!(value["attribute"], "name");
assert_eq!(value["values"][0], "Ann");
}
#[test]
fn test_not_ends_with() {
let query = Query::not_ends_with("name", "nne");
let value = query.to_value();
assert_eq!(value["method"], "notEndsWith");
assert_eq!(value["attribute"], "name");
assert_eq!(value["values"][0], "nne");
}
#[test]
fn test_created_before() {
let query = Query::created_before("2023-01-01");
let value = query.to_value();
assert_eq!(value["method"], "lessThan");
assert_eq!(value["attribute"], "$createdAt");
assert_eq!(value["values"][0], "2023-01-01");
}
#[test]
fn test_created_after() {
let query = Query::created_after("2023-01-01");
let value = query.to_value();
assert_eq!(value["method"], "greaterThan");
assert_eq!(value["attribute"], "$createdAt");
assert_eq!(value["values"][0], "2023-01-01");
}
#[test]
fn test_created_between() {
let query = Query::created_between("2023-01-01", "2023-12-31");
let value = query.to_value();
assert_eq!(value["method"], "between");
assert_eq!(value["attribute"], "$createdAt");
assert_eq!(value["values"][0], "2023-01-01");
assert_eq!(value["values"][1], "2023-12-31");
}
#[test]
fn test_updated_before() {
let query = Query::updated_before("2023-01-01");
let value = query.to_value();
assert_eq!(value["method"], "lessThan");
assert_eq!(value["attribute"], "$updatedAt");
assert_eq!(value["values"][0], "2023-01-01");
}
#[test]
fn test_updated_after() {
let query = Query::updated_after("2023-01-01");
let value = query.to_value();
assert_eq!(value["method"], "greaterThan");
assert_eq!(value["attribute"], "$updatedAt");
assert_eq!(value["values"][0], "2023-01-01");
}
#[test]
fn test_updated_between() {
let query = Query::updated_between("2023-01-01", "2023-12-31");
let value = query.to_value();
assert_eq!(value["method"], "between");
assert_eq!(value["attribute"], "$updatedAt");
assert_eq!(value["values"][0], "2023-01-01");
assert_eq!(value["values"][1], "2023-12-31");
}
#[test]
fn test_not_search() {
let query = Query::not_search("content", "spam keyword");
let value = query.to_value();
assert_eq!(value["method"], "notSearch");
assert_eq!(value["attribute"], "content");
assert_eq!(value["values"][0], "spam keyword");
}
}