cargo fmt

This commit is contained in:
qdequele 2020-08-17 17:43:05 +02:00 committed by qdequele
parent ab170ce4fd
commit 51fd849852
2 changed files with 185 additions and 91 deletions

View File

@ -1,9 +1,7 @@
use std::collections::{HashSet, HashMap}; use std::collections::{HashMap, HashSet};
use actix_web::{get, post, web, HttpResponse};
use log::warn; use log::warn;
use actix_web::web;
use actix_web::HttpResponse;
use actix_web::{get, post};
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use serde_json::Value; use serde_json::Value;
@ -14,11 +12,10 @@ use crate::routes::IndexParam;
use crate::Data; use crate::Data;
use meilisearch_core::facets::FacetFilter; use meilisearch_core::facets::FacetFilter;
use meilisearch_schema::{Schema, FieldId}; use meilisearch_schema::{FieldId, Schema};
pub fn services(cfg: &mut web::ServiceConfig) { pub fn services(cfg: &mut web::ServiceConfig) {
cfg.service(search_with_post) cfg.service(search_with_post).service(search_with_url_query);
.service(search_with_url_query);
} }
#[derive(Serialize, Deserialize)] #[derive(Serialize, Deserialize)]
@ -93,7 +90,11 @@ async fn search_with_post(
} }
impl SearchQuery { impl SearchQuery {
fn search(&self, index_uid: &str, data: web::Data<Data>) -> Result<SearchResult, ResponseError> { fn search(
&self,
index_uid: &str,
data: web::Data<Data>,
) -> Result<SearchResult, ResponseError> {
let index = data let index = data
.db .db
.open_index(index_uid) .open_index(index_uid)
@ -111,6 +112,7 @@ impl SearchQuery {
.and_then(|q| if q.is_empty() { None } else { Some(q) }); .and_then(|q| if q.is_empty() { None } else { Some(q) });
let mut search_builder = index.new_search(query); let mut search_builder = index.new_search(query);
if let Some(offset) = self.offset { if let Some(offset) = self.offset {
search_builder.offset(offset); search_builder.offset(offset);
} }
@ -122,7 +124,8 @@ impl SearchQuery {
let mut restricted_attributes: HashSet<&str>; let mut restricted_attributes: HashSet<&str>;
match &self.attributes_to_retrieve { match &self.attributes_to_retrieve {
Some(attributes_to_retrieve) => { Some(attributes_to_retrieve) => {
let attributes_to_retrieve: HashSet<&str> = attributes_to_retrieve.split(',').collect(); let attributes_to_retrieve: HashSet<&str> =
attributes_to_retrieve.split(',').collect();
if attributes_to_retrieve.contains("*") { if attributes_to_retrieve.contains("*") {
restricted_attributes = available_attributes.clone(); restricted_attributes = available_attributes.clone();
} else { } else {
@ -136,15 +139,22 @@ impl SearchQuery {
} }
} }
} }
}, }
None => { None => {
restricted_attributes = available_attributes.clone(); restricted_attributes = available_attributes.clone();
} }
} }
if let Some(ref facet_filters) = self.facet_filters { if let Some(ref facet_filters) = self.facet_filters {
let attrs = index.main.attributes_for_faceting(&reader)?.unwrap_or_default(); let attrs = index
search_builder.add_facet_filters(FacetFilter::from_str(facet_filters, &schema, &attrs)?); .main
.attributes_for_faceting(&reader)?
.unwrap_or_default();
search_builder.add_facet_filters(FacetFilter::from_str(
facet_filters,
&schema,
&attrs,
)?);
} }
if let Some(facets) = &self.facets_distribution { if let Some(facets) = &self.facets_distribution {
@ -152,7 +162,7 @@ impl SearchQuery {
Some(ref attrs) => { Some(ref attrs) => {
let field_ids = prepare_facet_list(&facets, &schema, attrs)?; let field_ids = prepare_facet_list(&facets, &schema, attrs)?;
search_builder.add_facets(field_ids); search_builder.add_facets(field_ids);
}, }
None => return Err(FacetCountError::NoFacetSet.into()), None => return Err(FacetCountError::NoFacetSet.into()),
} }
} }
@ -164,20 +174,23 @@ impl SearchQuery {
for attribute in attributes_to_crop.split(',') { for attribute in attributes_to_crop.split(',') {
let mut attribute = attribute.split(':'); let mut attribute = attribute.split(':');
let attr = attribute.next(); let attr = attribute.next();
let length = attribute.next().and_then(|s| s.parse().ok()).unwrap_or(default_length); let length = attribute
.next()
.and_then(|s| s.parse().ok())
.unwrap_or(default_length);
match attr { match attr {
Some("*") => { Some("*") => {
for attr in &restricted_attributes { for attr in &restricted_attributes {
final_attributes.insert(attr.to_string(), length); final_attributes.insert(attr.to_string(), length);
} }
}, }
Some(attr) => { Some(attr) => {
if available_attributes.contains(attr) { if available_attributes.contains(attr) {
final_attributes.insert(attr.to_string(), length); final_attributes.insert(attr.to_string(), length);
} else { } else {
warn!("The attributes {:?} present in attributesToCrop parameter doesn't exist", attr); warn!("The attributes {:?} present in attributesToCrop parameter doesn't exist", attr);
} }
}, }
None => (), None => (),
} }
} }
@ -219,7 +232,11 @@ impl SearchQuery {
/// ///
/// An error is returned if the array is malformed, or if it contains attributes that are /// An error is returned if the array is malformed, or if it contains attributes that are
/// unexisting, or not set as facets. /// unexisting, or not set as facets.
fn prepare_facet_list(facets: &str, schema: &Schema, facet_attrs: &[FieldId]) -> Result<Vec<(FieldId, String)>, FacetCountError> { fn prepare_facet_list(
facets: &str,
schema: &Schema,
facet_attrs: &[FieldId],
) -> Result<Vec<(FieldId, String)>, FacetCountError> {
let json_array = serde_json::from_str(facets)?; let json_array = serde_json::from_str(facets)?;
match json_array { match json_array {
Value::Array(vals) => { Value::Array(vals) => {
@ -247,6 +264,6 @@ fn prepare_facet_list(facets: &str, schema: &Schema, facet_attrs: &[FieldId]) ->
} }
Ok(field_ids) Ok(field_ids)
} }
bad_val => Err(FacetCountError::unexpected_token(bad_val, &["[String]"])) bad_val => Err(FacetCountError::unexpected_token(bad_val, &["[String]"])),
} }
} }

View File

@ -2,10 +2,11 @@ use std::convert::Into;
use serde_json::json; use serde_json::json;
use serde_json::Value; use serde_json::Value;
use std::sync::Mutex;
use std::cell::RefCell; use std::cell::RefCell;
use std::sync::Mutex;
#[macro_use] mod common; #[macro_use]
mod common;
#[actix_rt::test] #[actix_rt::test]
async fn placeholder_search_with_limit() { async fn placeholder_search_with_limit() {
@ -36,7 +37,12 @@ async fn placeholder_search_with_offset() {
assert_eq!(status_code, 200); assert_eq!(status_code, 200);
// take results at offset 3 as reference // take results at offset 3 as reference
let lock = expected.lock().unwrap(); let lock = expected.lock().unwrap();
lock.replace(response["hits"].as_array().unwrap()[3..6].iter().cloned().collect()); lock.replace(
response["hits"].as_array().unwrap()[3..6]
.iter()
.cloned()
.collect(),
);
}); });
let expected = expected.into_inner().unwrap().into_inner(); let expected = expected.into_inner().unwrap().into_inner();
@ -64,11 +70,7 @@ async fn placeholder_search_with_attribute_to_highlight_wildcard() {
test_post_get_search!(server, query, |response, status_code| { test_post_get_search!(server, query, |response, status_code| {
assert_eq!(status_code, 200); assert_eq!(status_code, 200);
let result = response["hits"] let result = response["hits"].as_array().unwrap()[0].as_object().unwrap();
.as_array()
.unwrap()[0]
.as_object()
.unwrap();
for value in result.values() { for value in result.values() {
assert!(value.to_string().find("<em>").is_none()); assert!(value.to_string().find("<em>").is_none());
} }
@ -135,11 +137,7 @@ async fn placeholder_search_with_attributes_to_retrieve() {
}); });
test_post_get_search!(server, query, |response, _status_code| { test_post_get_search!(server, query, |response, _status_code| {
let hit = response["hits"] let hit = response["hits"].as_array().unwrap()[0].as_object().unwrap();
.as_array()
.unwrap()[0]
.as_object()
.unwrap();
assert_eq!(hit.values().count(), 2); assert_eq!(hit.values().count(), 2);
let _ = hit["gender"]; let _ = hit["gender"];
let _ = hit["about"]; let _ = hit["about"];
@ -166,7 +164,9 @@ async fn placeholder_search_with_filter() {
test_post_get_search!(server, query, |response, _status_code| { test_post_get_search!(server, query, |response, _status_code| {
let hits = response["hits"].as_array().unwrap(); let hits = response["hits"].as_array().unwrap();
let value = Value::String(String::from("bug")); let value = Value::String(String::from("bug"));
assert!(hits.iter().all(|v| v["tags"].as_array().unwrap().contains(&value))); assert!(hits
.iter()
.all(|v| v["tags"].as_array().unwrap().contains(&value)));
}); });
let query = json!({ let query = json!({
@ -176,10 +176,9 @@ async fn placeholder_search_with_filter() {
let hits = response["hits"].as_array().unwrap(); let hits = response["hits"].as_array().unwrap();
let bug = Value::String(String::from("bug")); let bug = Value::String(String::from("bug"));
let wontfix = Value::String(String::from("wontfix")); let wontfix = Value::String(String::from("wontfix"));
assert!(hits.iter().all(|v| assert!(hits.iter().all(|v| v["color"].as_str().unwrap() == "Green"
v["color"].as_str().unwrap() == "Green" && && v["tags"].as_array().unwrap().contains(&bug)
v["tags"].as_array().unwrap().contains(&bug) || || v["tags"].as_array().unwrap().contains(&wontfix)));
v["tags"].as_array().unwrap().contains(&wontfix)));
}); });
} }
@ -257,7 +256,12 @@ async fn placeholder_test_faceted_search_valid() {
.as_array() .as_array()
.unwrap() .unwrap()
.iter() .iter()
.all(|value| value.get("tags").unwrap().as_array().unwrap().contains(&Value::String("bug".to_owned())))); .all(|value| value
.get("tags")
.unwrap()
.as_array()
.unwrap()
.contains(&Value::String("bug".to_owned()))));
}); });
// test and: ["color:blue", "tags:bug"] // test and: ["color:blue", "tags:bug"]
@ -272,10 +276,13 @@ async fn placeholder_test_faceted_search_valid() {
.as_array() .as_array()
.unwrap() .unwrap()
.iter() .iter()
.all(|value| value .all(|value| value.get("color").unwrap() == "blue"
.get("color") && value
.unwrap() == "blue" .get("tags")
&& value.get("tags").unwrap().as_array().unwrap().contains(&Value::String("bug".to_owned())))); .unwrap()
.as_array()
.unwrap()
.contains(&Value::String("bug".to_owned()))));
}); });
// test or: [["color:blue", "color:green"]] // test or: [["color:blue", "color:green"]]
@ -290,13 +297,8 @@ async fn placeholder_test_faceted_search_valid() {
.as_array() .as_array()
.unwrap() .unwrap()
.iter() .iter()
.all(|value| .all(|value| value.get("color").unwrap() == "blue"
value || value.get("color").unwrap() == "Green"));
.get("color")
.unwrap() == "blue"
|| value
.get("color")
.unwrap() == "Green"));
}); });
// test and-or: ["tags:bug", ["color:blue", "color:green"]] // test and-or: ["tags:bug", ["color:blue", "color:green"]]
let query = json!({ let query = json!({
@ -310,20 +312,14 @@ async fn placeholder_test_faceted_search_valid() {
.as_array() .as_array()
.unwrap() .unwrap()
.iter() .iter()
.all(|value| .all(|value| value
value
.get("tags") .get("tags")
.unwrap() .unwrap()
.as_array() .as_array()
.unwrap() .unwrap()
.contains(&Value::String("bug".to_owned())) .contains(&Value::String("bug".to_owned()))
&& (value && (value.get("color").unwrap() == "blue"
.get("color") || value.get("color").unwrap() == "Green")));
.unwrap() == "blue"
|| value
.get("color")
.unwrap() == "Green")));
}); });
} }
@ -335,7 +331,10 @@ async fn placeholder_test_faceted_search_invalid() {
let query = json!({ let query = json!({
"facetFilters": ["color:blue"] "facetFilters": ["color:blue"]
}); });
test_post_get_search!(server, query, |_response, status_code| assert_ne!(status_code, 202)); test_post_get_search!(server, query, |_response, status_code| assert_ne!(
status_code,
202
));
let body = json!({ let body = json!({
"attributesForFaceting": ["color", "tags"] "attributesForFaceting": ["color", "tags"]
@ -346,34 +345,52 @@ async fn placeholder_test_faceted_search_invalid() {
let query = json!({ let query = json!({
"facetFilters": [] "facetFilters": []
}); });
test_post_get_search!(server, query, |_response, status_code| assert_ne!(status_code, 202)); test_post_get_search!(server, query, |_response, status_code| assert_ne!(
status_code,
202
));
// [[]] // [[]]
let query = json!({ let query = json!({
"facetFilters": [[]] "facetFilters": [[]]
}); });
test_post_get_search!(server, query, |_response, status_code| assert_ne!(status_code, 202)); test_post_get_search!(server, query, |_response, status_code| assert_ne!(
status_code,
202
));
// ["color:green", []] // ["color:green", []]
let query = json!({ let query = json!({
"facetFilters": ["color:green", []] "facetFilters": ["color:green", []]
}); });
test_post_get_search!(server, query, |_response, status_code| assert_ne!(status_code, 202)); test_post_get_search!(server, query, |_response, status_code| assert_ne!(
status_code,
202
));
// too much depth // too much depth
// [[[]]] // [[[]]]
let query = json!({ let query = json!({
"facetFilters": [[[]]] "facetFilters": [[[]]]
}); });
test_post_get_search!(server, query, |_response, status_code| assert_ne!(status_code, 202)); test_post_get_search!(server, query, |_response, status_code| assert_ne!(
status_code,
202
));
// [["color:green", ["color:blue"]]] // [["color:green", ["color:blue"]]]
let query = json!({ let query = json!({
"facetFilters": [["color:green", ["color:blue"]]] "facetFilters": [["color:green", ["color:blue"]]]
}); });
test_post_get_search!(server, query, |_response, status_code| assert_ne!(status_code, 202)); test_post_get_search!(server, query, |_response, status_code| assert_ne!(
status_code,
202
));
// "color:green" // "color:green"
let query = json!({ let query = json!({
"facetFilters": "color:green" "facetFilters": "color:green"
}); });
test_post_get_search!(server, query, |_response, status_code| assert_ne!(status_code, 202)); test_post_get_search!(server, query, |_response, status_code| assert_ne!(
status_code,
202
));
} }
#[actix_rt::test] #[actix_rt::test]
@ -381,9 +398,8 @@ async fn placeholder_test_facet_count() {
let mut server = common::Server::test_server().await; let mut server = common::Server::test_server().await;
// test without facet distribution // test without facet distribution
let query = json!({ let query = json!({});
}); test_post_get_search!(server, query, |response, _status_code| {
test_post_get_search!(server, query, |response, _status_code|{
assert!(response.get("exhaustiveFacetsCount").is_none()); assert!(response.get("exhaustiveFacetsCount").is_none());
assert!(response.get("facetsDistribution").is_none()); assert!(response.get("facetsDistribution").is_none());
}); });
@ -392,7 +408,7 @@ async fn placeholder_test_facet_count() {
let query = json!({ let query = json!({
"facetsDistribution": ["color"] "facetsDistribution": ["color"]
}); });
test_post_get_search!(server, query.clone(), |_response, status_code|{ test_post_get_search!(server, query.clone(), |_response, status_code| {
assert_eq!(status_code, 400); assert_eq!(status_code, 400);
}); });
@ -401,52 +417,109 @@ async fn placeholder_test_facet_count() {
}); });
server.update_all_settings(body).await; server.update_all_settings(body).await;
// same as before, but now facets are set: // same as before, but now facets are set:
test_post_get_search!(server, query, |response, _status_code|{ test_post_get_search!(server, query, |response, _status_code| {
println!("{}", response); println!("{}", response);
assert!(response.get("exhaustiveFacetsCount").is_some()); assert!(response.get("exhaustiveFacetsCount").is_some());
assert_eq!(response.get("facetsDistribution").unwrap().as_object().unwrap().values().count(), 1); assert_eq!(
response
.get("facetsDistribution")
.unwrap()
.as_object()
.unwrap()
.values()
.count(),
1
);
}); });
// searching on color and tags // searching on color and tags
let query = json!({ let query = json!({
"facetsDistribution": ["color", "tags"] "facetsDistribution": ["color", "tags"]
}); });
test_post_get_search!(server, query, |response, _status_code|{ test_post_get_search!(server, query, |response, _status_code| {
let facets = response.get("facetsDistribution").unwrap().as_object().unwrap(); let facets = response
.get("facetsDistribution")
.unwrap()
.as_object()
.unwrap();
assert_eq!(facets.values().count(), 2); assert_eq!(facets.values().count(), 2);
assert_ne!(!facets.get("color").unwrap().as_object().unwrap().values().count(), 0); assert_ne!(
assert_ne!(!facets.get("tags").unwrap().as_object().unwrap().values().count(), 0); !facets
.get("color")
.unwrap()
.as_object()
.unwrap()
.values()
.count(),
0
);
assert_ne!(
!facets
.get("tags")
.unwrap()
.as_object()
.unwrap()
.values()
.count(),
0
);
}); });
// wildcard // wildcard
let query = json!({ let query = json!({
"facetsDistribution": ["*"] "facetsDistribution": ["*"]
}); });
test_post_get_search!(server, query, |response, _status_code|{ test_post_get_search!(server, query, |response, _status_code| {
assert_eq!(response.get("facetsDistribution").unwrap().as_object().unwrap().values().count(), 2); assert_eq!(
response
.get("facetsDistribution")
.unwrap()
.as_object()
.unwrap()
.values()
.count(),
2
);
}); });
// wildcard with other attributes: // wildcard with other attributes:
let query = json!({ let query = json!({
"facetsDistribution": ["color", "*"] "facetsDistribution": ["color", "*"]
}); });
test_post_get_search!(server, query, |response, _status_code|{ test_post_get_search!(server, query, |response, _status_code| {
assert_eq!(response.get("facetsDistribution").unwrap().as_object().unwrap().values().count(), 2); assert_eq!(
response
.get("facetsDistribution")
.unwrap()
.as_object()
.unwrap()
.values()
.count(),
2
);
}); });
// empty facet list // empty facet list
let query = json!({ let query = json!({
"facetsDistribution": [] "facetsDistribution": []
}); });
test_post_get_search!(server, query, |response, _status_code|{ test_post_get_search!(server, query, |response, _status_code| {
assert_eq!(response.get("facetsDistribution").unwrap().as_object().unwrap().values().count(), 0); assert_eq!(
response
.get("facetsDistribution")
.unwrap()
.as_object()
.unwrap()
.values()
.count(),
0
);
}); });
// attr not set as facet passed: // attr not set as facet passed:
let query = json!({ let query = json!({
"facetsDistribution": ["gender"] "facetsDistribution": ["gender"]
}); });
test_post_get_search!(server, query, |_response, status_code|{ test_post_get_search!(server, query, |_response, status_code| {
assert_eq!(status_code, 400); assert_eq!(status_code, 400);
}); });
} }
#[actix_rt::test] #[actix_rt::test]
@ -475,13 +548,15 @@ async fn placeholder_test_sort() {
"attributesForFaceting": ["color"] "attributesForFaceting": ["color"]
}); });
server.update_all_settings(body).await; server.update_all_settings(body).await;
let query = json!({ }); let query = json!({});
test_post_get_search!(server, query, |response, _status_code| { test_post_get_search!(server, query, |response, _status_code| {
let hits = response["hits"].as_array().unwrap(); let hits = response["hits"].as_array().unwrap();
hits.iter().map(|v| v["age"].as_u64().unwrap()).fold(0, |prev, cur| { hits.iter()
assert!(cur >= prev); .map(|v| v["age"].as_u64().unwrap())
cur .fold(0, |prev, cur| {
}); assert!(cur >= prev);
cur
});
}); });
let query = json!({ let query = json!({
@ -489,10 +564,12 @@ async fn placeholder_test_sort() {
}); });
test_post_get_search!(server, query, |response, _status_code| { test_post_get_search!(server, query, |response, _status_code| {
let hits = response["hits"].as_array().unwrap(); let hits = response["hits"].as_array().unwrap();
hits.iter().map(|v| v["age"].as_u64().unwrap()).fold(0, |prev, cur| { hits.iter()
assert!(cur >= prev); .map(|v| v["age"].as_u64().unwrap())
cur .fold(0, |prev, cur| {
}); assert!(cur >= prev);
cur
});
}); });
} }