Skip to content

Commit

Permalink
query api sort applied to database. #14
Browse files Browse the repository at this point in the history
  • Loading branch information
serayuzgur committed May 10, 2017
1 parent f488176 commit e35c828
Show file tree
Hide file tree
Showing 5 changed files with 183 additions and 6 deletions.
4 changes: 2 additions & 2 deletions src/database/query_api/filter.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
//! # query_api
//! All necessery functions for appliying query api to json results.
//! # filter
//! All necessery functions for appliying filtering to json results.
use serde_json::{Value, Error};
use serde_json;
use serde_json::error::ErrorCode::Message;
Expand Down
3 changes: 3 additions & 0 deletions src/database/query_api/mod.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
//! # query_api
//! All necessery functions for appliying query api to json results.
pub mod filter;
pub mod q;
pub mod sort;
// TODO:
// Get the result
// If it is List than do the ops
Expand Down
5 changes: 2 additions & 3 deletions src/database/query_api/q.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
//! # query_api
//! All necessery functions for appliying query api to json results.
//! # q
//! All necessery functions for appliying full-text search to json results.
use serde_json::Value;
use service::query_api::Queries;

Expand All @@ -18,7 +18,6 @@ pub fn apply(obj: &mut Value, queries: &Queries) {
for key in map.keys() {
if let Some(field) = item.get(key) {
if let &Value::String(ref f_str) = field {
println!("Checking - {}.contains({})", f_str, q);
valid = f_str.contains(q);
if valid {
break;
Expand Down
176 changes: 176 additions & 0 deletions src/database/query_api/sort.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,176 @@
//! # sort
//! All necessery functions for appliying sorting to json results.
use serde_json::Value;
use service::query_api::Queries;
use service::query_api::Sort;
use serde_json::Map;
use std::cmp::Ordering;

fn compare(a: &Map<String, Value>, b: &Map<String, Value>, sort_key: &String) -> Ordering {
if let Some(a_val) = a.get(sort_key) {
if let Some(b_val) = b.get(sort_key) {
match a_val {
&Value::Array(ref a_arr) => {
if let &Value::Array(ref b_arr) = b_val {
return a_arr.len().cmp(&b_arr.len());
} else {
return Ordering::Greater;
}
}
&Value::Object(ref a_obj) => {
if let &Value::Object(ref b_obj) = b_val {
return a_obj.len().cmp(&b_obj.len());
} else {
return Ordering::Greater;
}
}
&Value::Number(ref a_num) => {
if let &Value::Number(ref b_num) = b_val {
// TODO: clear unwraps
return a_num.as_f64()
.unwrap()
.partial_cmp(&b_num.as_f64().unwrap())
.unwrap();
} else {
return Ordering::Greater;
}
}
&Value::String(ref a_str) => {
if let &Value::String(ref b_str) = b_val {
return a_str.cmp(&b_str);
} else {
return Ordering::Greater;
}
}
&Value::Bool(a_bool) => {
if let &Value::Bool(b_bool) = b_val {
return a_bool.cmp(&b_bool);
} else {
return Ordering::Greater;
}
}
&Value::Null => {
if let &Value::Null = b_val {
return Ordering::Equal;
} else {
return Ordering::Less;
}
}
}
} else {
Ordering::Greater
}
} else {
if let Some(_) = b.get(sort_key) {
Ordering::Less
} else {
Ordering::Equal
}
}
}

/// sort on all desired fields fields according to the query api
pub fn apply(obj: &mut Value, queries: &Queries) {
if let &mut Value::Array(ref mut arr) = obj {
let ref sorts = queries.sort;
arr.sort_by(|a: &Value, b: &Value| {
match a {
&Value::Object(ref map_a) => {
if let &Value::Object(ref map_b) = b {
let mut result = Ordering::Equal;
for sort in sorts {
result = match sort {
&Sort::ASC(ref sort_key) => compare(&map_a, &map_b, &sort_key),
&Sort::DSC(ref sort_key) => compare(&map_b, &map_a, &sort_key),
};
if result != Ordering::Equal {
return result;
}
}
return result;
} else {
Ordering::Greater
}
}
_ => Ordering::Less,
}
});
};
}


#[cfg(test)]
mod tests {
use super::*;
use serde_json;
use service::query_api::Sort;

fn get_json() -> Value {
let json_string = r#"[
{
"name":"seray",
"age":31,
"active":true,
"password":"123"
},
{
"name":"kamil",
"age":900,
"active":false,
"password":"333"
},
{
"name":"recep",
"age":25,
"active":true,
"password":"3212"
},
{
"name":"hasan",
"age":25,
"active":true,
"password":"3212"
}
]"#;
serde_json::from_str(&json_string).unwrap()
}

#[test]
fn apply_sort_test() {
let mut queries = Queries::new();
{
queries.sort.push(Sort::ASC("age".to_string()));
queries.sort.push(Sort::ASC("name".to_string()));
}
let expected: Value = serde_json::from_str(&r#"[
{
"name":"hasan",
"age":25,
"active":true,
"password":"3212"
},
{
"name":"recep",
"age":25,
"active":true,
"password":"3212"
},
{
"name":"seray",
"age":31,
"active":true,
"password":"123"
},
{
"name":"kamil",
"age":900,
"active":false,
"password":"333"
}
]"#)
.unwrap();
let json = &mut get_json();
apply(json, &queries);
assert_eq!(json.clone(), expected);
}
}
1 change: 0 additions & 1 deletion src/database/read.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@ impl Database {
queries: Option<Queries>)
-> Result<Value, Errors> {
let mut data = &mut self.data;
// TODO: If path is db return db
match Self::get_object(keys, data) {
Ok(obj) => {
println!("{:?}", queries);
Expand Down

0 comments on commit e35c828

Please sign in to comment.