From 500eeca3fb0182c1c1ca3b5a784f37d2f83c8012 Mon Sep 17 00:00:00 2001 From: Quentin de Quelen Date: Thu, 2 Apr 2020 19:53:51 +0200 Subject: [PATCH 1/4] Rework query highlight/crop parameters --- meilisearch-http/src/helpers/meilisearch.rs | 80 +++++++++++++------- meilisearch-http/src/routes/search.rs | 82 +++++++++++++-------- 2 files changed, 104 insertions(+), 58 deletions(-) diff --git a/meilisearch-http/src/helpers/meilisearch.rs b/meilisearch-http/src/helpers/meilisearch.rs index 6cb1f97a3..9dba1696d 100644 --- a/meilisearch-http/src/helpers/meilisearch.rs +++ b/meilisearch-http/src/helpers/meilisearch.rs @@ -12,8 +12,8 @@ use meilisearch_core::Filter; use meilisearch_core::criterion::*; use meilisearch_core::settings::RankingRule; use meilisearch_core::{Highlight, Index, MainT, RankedMap}; -use meilisearch_tokenizer::is_cjk; use meilisearch_schema::{FieldId, Schema}; +use meilisearch_tokenizer::is_cjk; use serde::{Deserialize, Serialize}; use serde_json::Value; use siphasher::sip::SipHasher; @@ -220,36 +220,51 @@ impl<'a> SearchBuilder<'a> { } let start = Instant::now(); - let result = query_builder.query(reader, &self.query, self.offset..(self.offset + self.limit)); + let result = + query_builder.query(reader, &self.query, self.offset..(self.offset + self.limit)); let (docs, nb_hits) = result.map_err(|e| Error::SearchDocuments(e.to_string()))?; let time_ms = start.elapsed().as_millis() as usize; + let mut all_attributes: HashSet<&str> = HashSet::new(); + let mut all_formatted: HashSet<&str> = HashSet::new(); + + match &self.attributes_to_retrieve { + Some(to_retrieve) => { + all_attributes.extend(to_retrieve.iter().map(String::as_str)); + + if let Some(to_highlight) = &self.attributes_to_highlight { + all_formatted.extend(to_highlight.iter().map(String::as_str)); + } + + if let Some(to_crop) = &self.attributes_to_crop { + all_formatted.extend(to_crop.keys().map(String::as_str)); + } + + all_attributes.extend(&all_formatted); + }, + None => { + all_attributes.extend(schema.displayed_name()); + // If we specified at least one attribute to highlight or crop then + // all available attributes will be returned in the _formatted field. + if self.attributes_to_highlight.is_some() || self.attributes_to_crop.is_some() { + all_formatted.extend(all_attributes.iter().cloned()); + } + }, + } + let mut hits = Vec::with_capacity(self.limit); for doc in docs { - // retrieve the content of document in kv store - let mut fields: Option> = None; - if let Some(attributes_to_retrieve) = &self.attributes_to_retrieve { - let mut set = HashSet::new(); - for field in attributes_to_retrieve { - set.insert(field.as_str()); - } - fields = Some(set); - } - - let document: IndexMap = self + let mut document: IndexMap = self .index - .document(reader, fields.as_ref(), doc.id) + .document(reader, Some(&all_attributes), doc.id) .map_err(|e| Error::RetrieveDocument(doc.id.0, e.to_string()))? .ok_or(Error::DocumentNotFound(doc.id.0))?; - let has_attributes_to_highlight = self.attributes_to_highlight.is_some(); - let has_attributes_to_crop = self.attributes_to_crop.is_some(); + let mut formatted = document.iter() + .filter(|(key, _)| all_formatted.contains(key.as_str())) + .map(|(k, v)| (k.clone(), v.clone())) + .collect(); - let mut formatted = if has_attributes_to_highlight || has_attributes_to_crop { - document.clone() - } else { - IndexMap::new() - }; let mut matches = doc.highlights.clone(); // Crops fields if needed @@ -258,13 +273,24 @@ impl<'a> SearchBuilder<'a> { } // Transform to readable matches - let matches = calculate_matches(matches, self.attributes_to_retrieve.clone(), &schema); - if let Some(attributes_to_highlight) = &self.attributes_to_highlight { + let matches = calculate_matches( + matches.clone(), + self.attributes_to_highlight.clone(), + &schema, + ); formatted = calculate_highlights(&formatted, &matches, attributes_to_highlight); } - let matches_info = if self.matches { Some(matches) } else { None }; + let matches_info = if self.matches { + Some(calculate_matches(matches, self.attributes_to_retrieve.clone(), &schema)) + } else { + None + }; + + if let Some(attributes_to_retrieve) = &self.attributes_to_retrieve { + document.retain(|key, _| attributes_to_retrieve.contains(&key.to_string())) + } let hit = SearchHit { document, @@ -369,7 +395,7 @@ pub struct SearchResult { pub query: String, } -/// returns the start index and the length on the crop. +/// returns the start index and the length on the crop. fn aligned_crop(text: &str, match_index: usize, context: usize) -> (usize, usize) { let is_word_component = |c: &char| c.is_alphanumeric() && !is_cjk(*c); @@ -553,8 +579,8 @@ mod tests { let (start, length) = aligned_crop(&text, 5, 3); let cropped = text.chars().skip(start).take(length).collect::().trim().to_string(); assert_eq!("isのス", cropped); - - // split regular word / CJK word, no space + + // split regular word / CJK word, no space let (start, length) = aligned_crop(&text, 7, 1); let cropped = text.chars().skip(start).take(length).collect::().trim().to_string(); assert_eq!("のス", cropped); diff --git a/meilisearch-http/src/routes/search.rs b/meilisearch-http/src/routes/search.rs index 2dffd9356..a3a90391c 100644 --- a/meilisearch-http/src/routes/search.rs +++ b/meilisearch-http/src/routes/search.rs @@ -2,6 +2,7 @@ use std::collections::HashMap; use std::collections::HashSet; use std::time::Duration; +use log::warn; use meilisearch_core::Index; use rayon::iter::{IntoParallelIterator, ParallelIterator}; use serde::{Deserialize, Serialize}; @@ -53,45 +54,64 @@ pub async fn search_with_url_query(ctx: Request) -> SResult { search_builder.limit(limit); } - if let Some(attributes_to_retrieve) = query.attributes_to_retrieve { - for attr in attributes_to_retrieve.split(',') { - search_builder.add_retrievable_field(attr.to_string()); + let available_attributes = schema.displayed_name(); + let mut restricted_attributes: HashSet<&str>; + match &query.attributes_to_retrieve { + Some(attributes_to_retrieve) => { + restricted_attributes = attributes_to_retrieve.split(',').collect(); + restricted_attributes.retain(|attr| available_attributes.contains(attr)); + }, + None => { + restricted_attributes = available_attributes.clone(); } } if let Some(attributes_to_crop) = query.attributes_to_crop { - let crop_length = query.crop_length.unwrap_or(200); - if attributes_to_crop == "*" { - let attributes_to_crop = schema - .displayed_name() - .iter() - .map(|attr| (attr.to_string(), crop_length)) - .collect(); - search_builder.attributes_to_crop(attributes_to_crop); - } else { - let attributes_to_crop = attributes_to_crop - .split(',') - .map(|r| (r.to_string(), crop_length)) - .collect(); - search_builder.attributes_to_crop(attributes_to_crop); + let default_length = query.crop_length.unwrap_or(200); + let mut final_attributes: HashMap = HashMap::new(); + + for attribute in attributes_to_crop.split(',') { + let mut attribute = attribute.split(':'); + let attr = attribute.next(); + let length = attribute.next().and_then(|s| s.parse().ok()).unwrap_or(default_length); + match attr { + Some("*") => { + for attr in &restricted_attributes { + final_attributes.insert(attr.to_string(), length); + } + }, + Some(attr) => { + if available_attributes.contains(attr) { + final_attributes.insert(attr.to_string(), length); + } else { + warn!("The attributes {:?} present in attributesToCrop parameter doesn't exist", attr); + } + }, + None => (), + } } + + search_builder.attributes_to_crop(final_attributes); } - if let Some(attributes_to_highlight) = query.attributes_to_highlight { - let attributes_to_highlight = if attributes_to_highlight == "*" { - schema - .displayed_name() - .iter() - .map(|s| s.to_string()) - .collect() - } else { - attributes_to_highlight - .split(',') - .map(|s| s.to_string()) - .collect() - }; + if let Some(inline_attributes) = query.attributes_to_highlight { + let mut final_attributes: HashSet = HashSet::new(); - search_builder.attributes_to_highlight(attributes_to_highlight); + for attribute in inline_attributes.split(',') { + if attribute == "*" { + for attr in &restricted_attributes { + final_attributes.insert(attr.to_string()); + } + } else { + if available_attributes.contains(attribute) { + final_attributes.insert(attribute.to_string()); + } else { + warn!("The attributes {:?} present in attributesToHighlight parameter doesn't exist", attribute); + } + } + } + + search_builder.attributes_to_highlight(final_attributes); } if let Some(filters) = query.filters { From 644e78df89f4f1fd973854310f21a3dcdeda24a2 Mon Sep 17 00:00:00 2001 From: Quentin de Quelen Date: Fri, 3 Apr 2020 15:00:41 +0200 Subject: [PATCH 2/4] Add some tests --- Cargo.lock | 1 + meilisearch-http/Cargo.toml | 1 + meilisearch-http/tests/search.rs | 1011 ++++++--------------- meilisearch-http/tests/search_settings.rs | 679 ++++++++++++++ 4 files changed, 968 insertions(+), 724 deletions(-) create mode 100644 meilisearch-http/tests/search_settings.rs diff --git a/Cargo.lock b/Cargo.lock index b47eb42fe..16f482172 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1132,6 +1132,7 @@ dependencies = [ "meilisearch-schema", "meilisearch-tokenizer", "mime", + "once_cell", "pretty-bytes", "rand 0.7.3", "rayon", diff --git a/meilisearch-http/Cargo.toml b/meilisearch-http/Cargo.toml index f46eda499..86339b267 100644 --- a/meilisearch-http/Cargo.toml +++ b/meilisearch-http/Cargo.toml @@ -47,6 +47,7 @@ whoami = "0.8.1" http-service = "0.4.0" http-service-mock = "0.4.0" tempdir = "0.3.7" +once_cell = "1.3.1" [dev-dependencies.assert-json-diff] git = "https://github.com/qdequele/assert-json-diff" diff --git a/meilisearch-http/tests/search.rs b/meilisearch-http/tests/search.rs index 8ce170ec8..174894f7a 100644 --- a/meilisearch-http/tests/search.rs +++ b/meilisearch-http/tests/search.rs @@ -1,21 +1,26 @@ -use assert_json_diff::assert_json_eq; -use serde_json::json; use std::convert::Into; +use std::sync::Mutex; + +use assert_json_diff::assert_json_eq; +use once_cell::sync::Lazy; +use serde_json::json; mod common; -#[test] -fn basic_search() { +static GLOBAL_SERVER: Lazy> = Lazy::new(|| { let mut server = common::Server::with_uid("movies"); server.populate_movies(); + Mutex::new(server) +}); - // 1 - Simple search - // q: Captain - // limit: 3 - +// Search +// q: Captain +// limit: 3 +#[test] +fn search_with_limit() { let query = "q=captain&limit=3"; - let expect = json!([ + let expected = json!([ { "id": 299537, "popularity": 44.726, @@ -69,17 +74,19 @@ fn basic_search() { } ]); - let (response, _status_code) = server.search(query); - assert_json_eq!(expect, response["hits"].clone(), ordered: false); - - // 2 - Simple search with offset - // q: Captain - // limit: 3 - // offset: 1 + let (response, _status_code) = GLOBAL_SERVER.lock().unwrap().search(query); + assert_json_eq!(expected, response["hits"].clone(), ordered: false); +} +// Search with offset +// q: Captain +// limit: 3 +// offset: 1 +#[test] +fn search_with_offset() { let query = "q=captain&limit=3&offset=1"; - let expect = json!([ + let expected = json!([ { "id": 271110, "popularity": 37.431, @@ -134,17 +141,19 @@ fn basic_search() { } ]); - let (response, _status_code) = server.search(query); - assert_json_eq!(expect, response["hits"].clone(), ordered: false); - - // 3 - Simple search with attribute to highlight all - // q: Captain - // limit: 1 - // attributeToHighlight: * + let (response, _status_code) = GLOBAL_SERVER.lock().unwrap().search(query); + assert_json_eq!(expected, response["hits"].clone(), ordered: false); +} +// Search with attribute to highlight all +// q: Captain +// limit: 1 +// attributeToHighlight: * +#[test] +fn search_with_attribute_to_highlight_wildcard() { let query = "q=captain&limit=1&attributesToHighlight=*"; - let expect = json!([ + let expected = json!([ { "id": 299537, "popularity": 44.726, @@ -181,17 +190,19 @@ fn basic_search() { } ]); - let (response, _status_code) = server.search(query); - assert_json_eq!(expect, response["hits"].clone(), ordered: false); - - // 4 - Simple search with attribute to highlight title - // q: Captain - // limit: 1 - // attributeToHighlight: title + let (response, _status_code) = GLOBAL_SERVER.lock().unwrap().search(query); + assert_json_eq!(expected, response["hits"].clone(), ordered: false); +} +// Search with attribute to highlight title +// q: Captain +// limit: 1 +// attributeToHighlight: title +#[test] +fn search_with_attribute_to_highlight_1() { let query = "q=captain&limit=1&attributesToHighlight=title"; - let expect = json!([ + let expected = json!([ { "id": 299537, "popularity": 44.726, @@ -228,17 +239,19 @@ fn basic_search() { } ]); - let (response, _status_code) = server.search(query); - assert_json_eq!(expect, response["hits"].clone(), ordered: false); - - // 1 - Simple search with attribute to highlight title and tagline - // q: Captain - // limit: 1 - // attributeToHighlight: title,tagline + let (response, _status_code) = GLOBAL_SERVER.lock().unwrap().search(query); + assert_json_eq!(expected, response["hits"].clone(), ordered: false); +} +// Search with attribute to highlight title and tagline +// q: Captain +// limit: 1 +// attributeToHighlight: title,tagline +#[test] +fn search_with_attribute_to_highlight_title_tagline() { let query = "q=captain&limit=1&attributesToHighlight=title,tagline"; - let expect = json!([ + let expected = json!([ { "id": 299537, "popularity": 44.726, @@ -275,17 +288,19 @@ fn basic_search() { } ]); - let (response, _status_code) = server.search(query); - assert_json_eq!(expect, response["hits"].clone(), ordered: false); - - // 1 - Simple search with attribute to highlight title and overview - // q: Captain - // limit: 1 - // attributeToHighlight: title,overview + let (response, _status_code) = GLOBAL_SERVER.lock().unwrap().search(query); + assert_json_eq!(expected, response["hits"].clone(), ordered: false); +} +// Search with attribute to highlight title and overview +// q: Captain +// limit: 1 +// attributeToHighlight: title,overview +#[test] +fn search_with_attribute_to_highlight_title_overview() { let query = "q=captain&limit=1&attributesToHighlight=title,overview"; - let expect = json!([ + let expected = json!([ { "id": 299537, "popularity": 44.726, @@ -322,17 +337,19 @@ fn basic_search() { } ]); - let (response, _status_code) = server.search(query); - assert_json_eq!(expect, response["hits"].clone(), ordered: false); - - // 1 - Simple search with matches - // q: Captain - // limit: 1 - // matches: true + let (response, _status_code) = GLOBAL_SERVER.lock().unwrap().search(query); + assert_json_eq!(expected, response["hits"].clone(), ordered: false); +} +// Search with matches +// q: Captain +// limit: 1 +// matches: true +#[test] +fn search_with_matches() { let query = "q=captain&limit=1&matches=true"; - let expect = json!([ + let expected = json!([ { "id": 299537, "popularity": 44.726, @@ -366,18 +383,20 @@ fn basic_search() { } ]); - let (response, _status_code) = server.search(query); - assert_json_eq!(expect, response["hits"].clone(), ordered: false); - - // 1 - Simple search with crop - // q: Captain - // limit: 1 - // attributesToCrop: overview - // cropLength: 20 + let (response, _status_code) = GLOBAL_SERVER.lock().unwrap().search(query); + assert_json_eq!(expected, response["hits"].clone(), ordered: false); +} +// Search with crop +// q: Captain +// limit: 1 +// attributesToCrop: overview +// cropLength: 20 +#[test] +fn search_witch_crop() { let query = "q=captain&limit=1&attributesToCrop=overview&cropLength=20"; - let expect = json!([ + let expected = json!([ { "id": 299537, "popularity": 44.726, @@ -414,17 +433,19 @@ fn basic_search() { } ]); - let (response, _status_code) = server.search(query); - assert_json_eq!(expect, response["hits"].clone(), ordered: false); - - // 1 - Simple search with attributes to retrieve - // q: Captain - // limit: 1 - // attributesToRetrieve: [title,tagline,overview,poster_path] + let (response, _status_code) = GLOBAL_SERVER.lock().unwrap().search(query); + assert_json_eq!(expected, response["hits"].clone(), ordered: false); +} +// Search with attributes to retrieve +// q: Captain +// limit: 1 +// attributesToRetrieve: [title,tagline,overview,poster_path] +#[test] +fn search_with_attributes_to_retrieve() { let query = "q=captain&limit=1&attributesToRetrieve=title,tagline,overview,poster_path"; - let expect = json!([ + let expected = json!([ { "title": "Captain Marvel", "tagline": "Higher. Further. Faster.", @@ -433,17 +454,19 @@ fn basic_search() { } ]); - let (response, _status_code) = server.search(query); - assert_json_eq!(expect, response["hits"].clone(), ordered: false); - - // 1 - Simple search with filter - // q: Captain - // limit: 3 - // filters: director:Anthony%20Russo + let (response, _status_code) = GLOBAL_SERVER.lock().unwrap().search(query); + assert_json_eq!(expected, response["hits"].clone(), ordered: false); +} +// Search with filter +// q: Captain +// limit: 1 +// filters: director:Anthony%20Russo +#[test] +fn search_with_filter() { let query = "q=captain&filters=director%20%3D%20%22Anthony%20Russo%22&limit=3"; - let expect = json!([ + let expected = json!([ { "id": 271110, "popularity": 37.431, @@ -497,18 +520,20 @@ fn basic_search() { } ]); - let (response, _status_code) = server.search(query); - assert_json_eq!(expect, response["hits"].clone(), ordered: false); - - // 1 - Simple search with attributes to highlight and matches - // q: Captain - // limit: 1 - // attributesToHighlight: [title,overview] - // matches: true + let (response, _status_code) = GLOBAL_SERVER.lock().unwrap().search(query); + assert_json_eq!(expected, response["hits"].clone(), ordered: false); +} +// Search with attributes to highlight and matches +// q: Captain +// limit: 1 +// attributesToHighlight: [title,overview] +// matches: true +#[test] +fn search_with_attributes_to_highlight_and_matches() { let query = "q=captain&limit=1&attributesToHighlight=title,overview&matches=true"; - let expect = json!( [ + let expected = json!( [ { "id": 299537, "popularity": 44.726, @@ -559,20 +584,22 @@ fn basic_search() { } ]); - let (response, _status_code) = server.search(query); - assert_json_eq!(expect, response["hits"].clone(), ordered: false); - - // 1 - Simple search with attributes to highlight and matches and crop - // q: Captain - // limit: 1 - // attributesToHighlight: [title,overview] - // matches: true - // cropLength: 20 - // attributesToCrop: overview + let (response, _status_code) = GLOBAL_SERVER.lock().unwrap().search(query); + assert_json_eq!(expected, response["hits"].clone(), ordered: false); +} +// Search with attributes to highlight and matches and crop +// q: Captain +// limit: 1 +// attributesToHighlight: [title,overview] +// matches: true +// cropLength: 20 +// attributesToCrop: overview +#[test] +fn search_with_attributes_to_highlight_and_matches_and_crop() { let query = "q=captain&limit=1&attributesToCrop=overview&cropLength=20&attributesToHighlight=title,overview&matches=true"; - let expect = json!([ + let expected = json!([ { "id": 299537, "popularity": 44.726, @@ -623,680 +650,216 @@ fn basic_search() { } ]); - let (response, _status_code) = server.search(query); - assert_json_eq!(expect, response["hits"].clone(), ordered: false); + let (response, _status_code) = GLOBAL_SERVER.lock().unwrap().search(query); + assert_json_eq!(expected, response["hits"].clone(), ordered: false); } +// Search with differents attributes +// q: Captain +// limit: 1 +// attributesToRetrieve: [title,producer,director] +// attributesToHighlight: [title] #[test] -fn search_with_settings_basic() { - let mut server = common::Server::with_uid("movies"); - server.populate_movies(); +fn search_with_differents_attributes() { + let query = "q=captain&limit=1&attributesToRetrieve=title,producer,director&attributesToHighlight=title"; - let config = json!({ - "rankingRules": [ - "typo", - "words", - "proximity", - "attribute", - "wordsPosition", - "desc(popularity)", - "exactness", - "desc(vote_average)" - ], - "distinctAttribute": null, - "searchableAttributes": [ - "title", - "tagline", - "overview", - "cast", - "director", - "producer", - "production_companies", - "genres" - ], - "displayedAttributes": [ - "title", - "director", - "producer", - "tagline", - "genres", - "id", - "overview", - "vote_count", - "vote_average", - "poster_path", - "popularity" - ], - "stopWords": null, - "synonyms": null, - "acceptNewFields": false, - }); - - server.update_all_settings(config); - - let query = "q=the%20avangers&limit=3"; - let expect = json!([ + let expected = json!([ { - "id": 24428, - "popularity": 44.506, - "vote_average": 7.7, - "title": "The Avengers", - "tagline": "Some assembly required.", - "overview": "When an unexpected enemy emerges and threatens global safety and security, Nick Fury, director of the international peacekeeping agency known as S.H.I.E.L.D., finds himself in need of a team to pull the world back from the brink of disaster. Spanning the globe, a daring recruitment effort begins!", - "director": "Joss Whedon", + "title": "Captain Marvel", + "director": "Ryan Fleck", "producer": "Kevin Feige", - "genres": [ - "Science Fiction", - "Action", - "Adventure" - ], - "poster_path": "https://image.tmdb.org/t/p/w500/cezWGskPY5x7GaglTTRN4Fugfb8.jpg", - "vote_count": 21079 - }, - { - "id": 299534, - "popularity": 38.659, - "vote_average": 8.3, - "title": "Avengers: Endgame", - "tagline": "Part of the journey is the end.", - "overview": "After the devastating events of Avengers: Infinity War, the universe is in ruins due to the efforts of the Mad Titan, Thanos. With the help of remaining allies, the Avengers must assemble once more in order to undo Thanos' actions and restore order to the universe once and for all, no matter what consequences may be in store.", - "director": "Anthony Russo", - "producer": "Kevin Feige", - "genres": [ - "Adventure", - "Science Fiction", - "Action" - ], - "poster_path": "https://image.tmdb.org/t/p/w500/or06FN3Dka5tukK1e9sl16pB3iy.jpg", - "vote_count": 10497 - }, - { - "id": 299536, - "popularity": 65.013, - "vote_average": 8.3, - "title": "Avengers: Infinity War", - "tagline": "An entire universe. Once and for all.", - "overview": "As the Avengers and their allies have continued to protect the world from threats too large for any one hero to handle, a new danger has emerged from the cosmic shadows: Thanos. A despot of intergalactic infamy, his goal is to collect all six Infinity Stones, artifacts of unimaginable power, and use them to inflict his twisted will on all of reality. Everything the Avengers have fought for has led up to this moment - the fate of Earth and existence itself has never been more uncertain.", - "director": "Anthony Russo", - "producer": "Kevin Feige", - "genres": [ - "Adventure", - "Action", - "Science Fiction" - ], - "poster_path": "https://image.tmdb.org/t/p/w500/7WsyChQLEftFiDOVTGkv3hFpyyt.jpg", - "vote_count": 16056 + "_formatted": { + "title": "Captain Marvel" + } } ]); - let (response, _status_code) = server.search(query); - assert_json_eq!(expect, response["hits"].clone(), ordered: false); + let (response, _status_code) = GLOBAL_SERVER.lock().unwrap().search(query); + assert_json_eq!(expected, response["hits"].clone(), ordered: false); } +// Search with attributes to highlight and matches and crop +// q: Captain +// limit: 1 +// attributesToRetrieve: [title,producer,director] +// attributesToCrop: [overview] +// cropLength: 10 #[test] -fn search_with_settings_stop_words() { - let mut server = common::Server::with_uid("movies"); - server.populate_movies(); +fn search_with_differents_attributes_2() { + let query = "q=captain&limit=1&attributesToRetrieve=title,producer,director&attributesToCrop=overview&cropLength=10"; - let config = json!({ - "rankingRules": [ - "typo", - "words", - "proximity", - "attribute", - "wordsPosition", - "desc(popularity)", - "exactness", - "desc(vote_average)" - ], - "distinctAttribute": null, - "searchableAttributes": [ - "title", - "tagline", - "overview", - "cast", - "director", - "producer", - "production_companies", - "genres" - ], - "displayedAttributes": [ - "title", - "director", - "producer", - "tagline", - "genres", - "id", - "overview", - "vote_count", - "vote_average", - "poster_path", - "popularity" - ], - "stopWords": ["the"], - "synonyms": null, - "acceptNewFields": false, - }); - - server.update_all_settings(config); - - let query = "q=the%20avangers&limit=3"; - let expect = json!([ + let expected = json!([ { - "id": 299536, - "popularity": 65.013, - "vote_average": 8.3, - "title": "Avengers: Infinity War", - "tagline": "An entire universe. Once and for all.", - "overview": "As the Avengers and their allies have continued to protect the world from threats too large for any one hero to handle, a new danger has emerged from the cosmic shadows: Thanos. A despot of intergalactic infamy, his goal is to collect all six Infinity Stones, artifacts of unimaginable power, and use them to inflict his twisted will on all of reality. Everything the Avengers have fought for has led up to this moment - the fate of Earth and existence itself has never been more uncertain.", - "director": "Anthony Russo", - "producer": "Kevin Feige", - "genres": [ - "Adventure", - "Action", - "Science Fiction" - ], - "poster_path": "https://image.tmdb.org/t/p/w500/7WsyChQLEftFiDOVTGkv3hFpyyt.jpg", - "vote_count": 16056 - }, - { - "id": 299534, - "popularity": 38.659, - "vote_average": 8.3, - "title": "Avengers: Endgame", - "tagline": "Part of the journey is the end.", - "overview": "After the devastating events of Avengers: Infinity War, the universe is in ruins due to the efforts of the Mad Titan, Thanos. With the help of remaining allies, the Avengers must assemble once more in order to undo Thanos' actions and restore order to the universe once and for all, no matter what consequences may be in store.", - "director": "Anthony Russo", - "producer": "Kevin Feige", - "genres": [ - "Adventure", - "Science Fiction", - "Action" - ], - "poster_path": "https://image.tmdb.org/t/p/w500/or06FN3Dka5tukK1e9sl16pB3iy.jpg", - "vote_count": 10497 - }, - { - "id": 99861, - "popularity": 33.938, - "vote_average": 7.3, - "title": "Avengers: Age of Ultron", - "tagline": "A New Age Has Come.", - "overview": "When Tony Stark tries to jumpstart a dormant peacekeeping program, things go awry and Earth’s Mightiest Heroes are put to the ultimate test as the fate of the planet hangs in the balance. As the villainous Ultron emerges, it is up to The Avengers to stop him from enacting his terrible plans, and soon uneasy alliances and unexpected action pave the way for an epic and unique global adventure.", - "director": "Joss Whedon", - "producer": "Kevin Feige", - "genres": [ - "Action", - "Adventure", - "Science Fiction" - ], - "poster_path": "https://image.tmdb.org/t/p/w500/t90Y3G8UGQp0f0DrP60wRu9gfrH.jpg", - "vote_count": 14661 + "title": "Captain Marvel", + "director": "Ryan Fleck", + "producer": "Kevin Feige", + "_formatted": { + "overview": "1990s, Captain Marvel" } + } ]); - let (response, _status_code) = server.search(query); - assert_json_eq!(expect, response["hits"].clone(), ordered: false); + let (response, _status_code) = GLOBAL_SERVER.lock().unwrap().search(query); + assert_json_eq!(expected, response["hits"].clone(), ordered: false); } +// Search with attributes to highlight and matches and crop +// q: Captain +// limit: 1 +// attributesToRetrieve: [title,producer,director] +// attributesToCrop: [overview:10] #[test] -fn search_with_settings_synonyms() { - let mut server = common::Server::with_uid("movies"); - server.populate_movies(); +fn search_with_differents_attributes_3() { + let query = "q=captain&limit=1&attributesToRetrieve=title,producer,director&attributesToCrop=overview:10"; - let config = json!({ - "rankingRules": [ - "typo", - "words", - "proximity", - "attribute", - "wordsPosition", - "desc(popularity)", - "exactness", - "desc(vote_average)" - ], - "distinctAttribute": null, - "searchableAttributes": [ - "title", - "tagline", - "overview", - "cast", - "director", - "producer", - "production_companies", - "genres" - ], - "displayedAttributes": [ - "title", - "director", - "producer", - "tagline", - "genres", - "id", - "overview", - "vote_count", - "vote_average", - "poster_path", - "popularity" - ], - "stopWords": null, - "synonyms": { - "avangers": [ - "Captain America", - "Iron Man" - ] - }, - "acceptNewFields": false, - }); - - server.update_all_settings(config); - - let query = "q=avangers&limit=3"; - let expect = json!([ + let expected = json!([ { - "id": 299536, - "popularity": 65.013, - "vote_average": 8.3, - "title": "Avengers: Infinity War", - "tagline": "An entire universe. Once and for all.", - "overview": "As the Avengers and their allies have continued to protect the world from threats too large for any one hero to handle, a new danger has emerged from the cosmic shadows: Thanos. A despot of intergalactic infamy, his goal is to collect all six Infinity Stones, artifacts of unimaginable power, and use them to inflict his twisted will on all of reality. Everything the Avengers have fought for has led up to this moment - the fate of Earth and existence itself has never been more uncertain.", - "director": "Anthony Russo", - "producer": "Kevin Feige", - "genres": [ - "Adventure", - "Action", - "Science Fiction" - ], - "vote_count": 16056, - "poster_path": "https://image.tmdb.org/t/p/w500/7WsyChQLEftFiDOVTGkv3hFpyyt.jpg" - }, - { - "id": 299534, - "popularity": 38.659, - "vote_average": 8.3, - "title": "Avengers: Endgame", - "tagline": "Part of the journey is the end.", - "overview": "After the devastating events of Avengers: Infinity War, the universe is in ruins due to the efforts of the Mad Titan, Thanos. With the help of remaining allies, the Avengers must assemble once more in order to undo Thanos' actions and restore order to the universe once and for all, no matter what consequences may be in store.", - "director": "Anthony Russo", - "producer": "Kevin Feige", - "genres": [ - "Adventure", - "Science Fiction", - "Action" - ], - "vote_count": 10497, - "poster_path": "https://image.tmdb.org/t/p/w500/or06FN3Dka5tukK1e9sl16pB3iy.jpg" - }, - { - "id": 99861, - "popularity": 33.938, - "vote_average": 7.3, - "title": "Avengers: Age of Ultron", - "tagline": "A New Age Has Come.", - "overview": "When Tony Stark tries to jumpstart a dormant peacekeeping program, things go awry and Earth’s Mightiest Heroes are put to the ultimate test as the fate of the planet hangs in the balance. As the villainous Ultron emerges, it is up to The Avengers to stop him from enacting his terrible plans, and soon uneasy alliances and unexpected action pave the way for an epic and unique global adventure.", - "director": "Joss Whedon", - "producer": "Kevin Feige", - "genres": [ - "Action", - "Adventure", - "Science Fiction" - ], - "vote_count": 14661, - "poster_path": "https://image.tmdb.org/t/p/w500/t90Y3G8UGQp0f0DrP60wRu9gfrH.jpg" + "title": "Captain Marvel", + "director": "Ryan Fleck", + "producer": "Kevin Feige", + "_formatted": { + "overview": "1990s, Captain Marvel" } + } ]); - let (response, _status_code) = server.search(query); - assert_json_eq!(expect, response["hits"].clone(), ordered: false); + let (response, _status_code) = GLOBAL_SERVER.lock().unwrap().search(query); + assert_json_eq!(expected, response["hits"].clone(), ordered: false); } +// Search with attributes to highlight and matches and crop +// q: Captain +// limit: 1 +// attributesToRetrieve: [title,producer,director] +// attributesToCrop: [overview:10,title:0] #[test] -fn search_with_settings_ranking_rules() { - let mut server = common::Server::with_uid("movies"); - server.populate_movies(); +fn search_with_differents_attributes_4() { + let query = "q=captain&limit=1&attributesToRetrieve=title,producer,director&attributesToCrop=overview:10,title:0"; - let config = json!({ - "rankingRules": [ - "typo", - "words", - "proximity", - "attribute", - "wordsPosition", - "asc(vote_average)", - "exactness", - "desc(popularity)" - ], - "distinctAttribute": null, - "searchableAttributes": [ - "title", - "tagline", - "overview", - "cast", - "director", - "producer", - "production_companies", - "genres" - ], - "displayedAttributes": [ - "title", - "director", - "producer", - "tagline", - "genres", - "id", - "overview", - "vote_count", - "vote_average", - "poster_path", - "popularity" - ], - "stopWords": null, - "synonyms": null, - "acceptNewFields": false, - }); - - server.update_all_settings(config); - - let query = "q=avangers&limit=3"; - let expect = json!([ - { - "id": 99861, - "popularity": 33.938, - "vote_average": 7.3, - "title": "Avengers: Age of Ultron", - "tagline": "A New Age Has Come.", - "overview": "When Tony Stark tries to jumpstart a dormant peacekeeping program, things go awry and Earth’s Mightiest Heroes are put to the ultimate test as the fate of the planet hangs in the balance. As the villainous Ultron emerges, it is up to The Avengers to stop him from enacting his terrible plans, and soon uneasy alliances and unexpected action pave the way for an epic and unique global adventure.", - "director": "Joss Whedon", - "producer": "Kevin Feige", - "genres": [ - "Action", - "Adventure", - "Science Fiction" - ], - "poster_path": "https://image.tmdb.org/t/p/w500/t90Y3G8UGQp0f0DrP60wRu9gfrH.jpg", - "vote_count": 14661 - }, - { - "id": 299536, - "popularity": 65.013, - "vote_average": 8.3, - "title": "Avengers: Infinity War", - "tagline": "An entire universe. Once and for all.", - "overview": "As the Avengers and their allies have continued to protect the world from threats too large for any one hero to handle, a new danger has emerged from the cosmic shadows: Thanos. A despot of intergalactic infamy, his goal is to collect all six Infinity Stones, artifacts of unimaginable power, and use them to inflict his twisted will on all of reality. Everything the Avengers have fought for has led up to this moment - the fate of Earth and existence itself has never been more uncertain.", - "director": "Anthony Russo", - "producer": "Kevin Feige", - "genres": [ - "Adventure", - "Action", - "Science Fiction" - ], - "poster_path": "https://image.tmdb.org/t/p/w500/7WsyChQLEftFiDOVTGkv3hFpyyt.jpg", - "vote_count": 16056 - }, - { - "id": 299534, - "popularity": 38.659, - "vote_average": 8.3, - "title": "Avengers: Endgame", - "tagline": "Part of the journey is the end.", - "overview": "After the devastating events of Avengers: Infinity War, the universe is in ruins due to the efforts of the Mad Titan, Thanos. With the help of remaining allies, the Avengers must assemble once more in order to undo Thanos' actions and restore order to the universe once and for all, no matter what consequences may be in store.", - "director": "Anthony Russo", - "producer": "Kevin Feige", - "genres": [ - "Adventure", - "Science Fiction", - "Action" - ], - "poster_path": "https://image.tmdb.org/t/p/w500/or06FN3Dka5tukK1e9sl16pB3iy.jpg", - "vote_count": 10497 + let expected = json!([ + { + "title": "Captain Marvel", + "director": "Ryan Fleck", + "producer": "Kevin Feige", + "_formatted": { + "title": "Captain", + "overview": "1990s, Captain Marvel" } + } ]); - let (response, _status_code) = server.search(query); - assert_json_eq!(expect, response["hits"].clone(), ordered: false); + let (response, _status_code) = GLOBAL_SERVER.lock().unwrap().search(query); + assert_json_eq!(expected, response["hits"].clone(), ordered: false); } +// Search with attributes to highlight and matches and crop +// q: Captain +// limit: 1 +// attributesToRetrieve: [title,producer,director] +// attributesToCrop: [*,overview:10] #[test] -fn search_with_settings_searchable_attributes() { - let mut server = common::Server::with_uid("movies"); - server.populate_movies(); +fn search_with_differents_attributes_5() { + let query = "q=captain&limit=1&attributesToRetrieve=title,producer,director&attributesToCrop=*,overview:10"; - let config = json!({ - "rankingRules": [ - "typo", - "words", - "proximity", - "attribute", - "wordsPosition", - "desc(popularity)", - "exactness", - "desc(vote_average)" - ], - "distinctAttribute": null, - "searchableAttributes": [ - "tagline", - "overview", - "cast", - "director", - "producer", - "production_companies", - "genres" - ], - "displayedAttributes": [ - "title", - "director", - "producer", - "tagline", - "genres", - "id", - "overview", - "vote_count", - "vote_average", - "poster_path", - "popularity" - ], - "stopWords": null, - "synonyms": null, - "acceptNewFields": false, - }); - - server.update_all_settings(config); - - let query = "q=avangers&limit=3"; - let expect = json!([ - { - "id": 299536, - "popularity": 65.013, - "vote_average": 8.3, - "title": "Avengers: Infinity War", - "tagline": "An entire universe. Once and for all.", - "overview": "As the Avengers and their allies have continued to protect the world from threats too large for any one hero to handle, a new danger has emerged from the cosmic shadows: Thanos. A despot of intergalactic infamy, his goal is to collect all six Infinity Stones, artifacts of unimaginable power, and use them to inflict his twisted will on all of reality. Everything the Avengers have fought for has led up to this moment - the fate of Earth and existence itself has never been more uncertain.", - "director": "Anthony Russo", + let expected = json!([ + { + "title": "Captain Marvel", + "director": "Ryan Fleck", + "producer": "Kevin Feige", + "_formatted": { + "title": "Captain Marvel", + "director": "Ryan Fleck", "producer": "Kevin Feige", - "genres": [ - "Adventure", - "Action", - "Science Fiction" - ], - "poster_path": "https://image.tmdb.org/t/p/w500/7WsyChQLEftFiDOVTGkv3hFpyyt.jpg", - "vote_count": 16056 - }, - { - "id": 299534, - "popularity": 38.659, - "vote_average": 8.3, - "title": "Avengers: Endgame", - "tagline": "Part of the journey is the end.", - "overview": "After the devastating events of Avengers: Infinity War, the universe is in ruins due to the efforts of the Mad Titan, Thanos. With the help of remaining allies, the Avengers must assemble once more in order to undo Thanos' actions and restore order to the universe once and for all, no matter what consequences may be in store.", - "director": "Anthony Russo", - "producer": "Kevin Feige", - "genres": [ - "Adventure", - "Science Fiction", - "Action" - ], - "poster_path": "https://image.tmdb.org/t/p/w500/or06FN3Dka5tukK1e9sl16pB3iy.jpg", - "vote_count": 10497 - }, - { - "id": 100402, - "popularity": 16.418, - "vote_average": 7.7, - "title": "Captain America: The Winter Soldier", - "tagline": "In heroes we trust.", - "overview": "After the cataclysmic events in New York with The Avengers, Steve Rogers, aka Captain America is living quietly in Washington, D.C. and trying to adjust to the modern world. But when a S.H.I.E.L.D. colleague comes under attack, Steve becomes embroiled in a web of intrigue that threatens to put the world at risk. Joining forces with the Black Widow, Captain America struggles to expose the ever-widening conspiracy while fighting off professional assassins sent to silence him at every turn. When the full scope of the villainous plot is revealed, Captain America and the Black Widow enlist the help of a new ally, the Falcon. However, they soon find themselves up against an unexpected and formidable enemy—the Winter Soldier.", - "director": "Anthony Russo", - "producer": "Kevin Feige", - "genres": [ - "Action", - "Adventure", - "Science Fiction" - ], - "poster_path": "https://image.tmdb.org/t/p/w500/5TQ6YDmymBpnF005OyoB7ohZps9.jpg", - "vote_count": 11972 + "overview": "1990s, Captain Marvel" } + } ]); - let (response, _status_code) = server.search(query); - assert_json_eq!(expect, response["hits"].clone(), ordered: false); + let (response, _status_code) = GLOBAL_SERVER.lock().unwrap().search(query); + assert_json_eq!(expected, response["hits"].clone(), ordered: false); } +// Search with attributes to highlight and matches and crop +// q: Captain +// limit: 1 +// attributesToRetrieve: [title,producer,director] +// attributesToCrop: [*,overview:10] +// attributesToHighlight: [title] #[test] -fn search_with_settings_displayed_attributes() { - let mut server = common::Server::with_uid("movies"); - server.populate_movies(); +fn search_with_differents_attributes_6() { + let query = "q=captain&limit=1&attributesToRetrieve=title,producer,director&attributesToCrop=*,overview:10&attributesToHighlight=title"; - let config = json!({ - "rankingRules": [ - "typo", - "words", - "proximity", - "attribute", - "wordsPosition", - "desc(popularity)", - "exactness", - "desc(vote_average)" - ], - "distinctAttribute": null, - "searchableAttributes": [ - "title", - "tagline", - "overview", - "cast", - "director", - "producer", - "production_companies", - "genres" - ], - "displayedAttributes": [ - "title", - "tagline", - "id", - "overview", - "poster_path" - ], - "stopWords": null, - "synonyms": null, - "acceptNewFields": false, - }); - - server.update_all_settings(config); - - let query = "q=avangers&limit=3"; - let expect = json!([ - { - "id": 299536, - "title": "Avengers: Infinity War", - "tagline": "An entire universe. Once and for all.", - "overview": "As the Avengers and their allies have continued to protect the world from threats too large for any one hero to handle, a new danger has emerged from the cosmic shadows: Thanos. A despot of intergalactic infamy, his goal is to collect all six Infinity Stones, artifacts of unimaginable power, and use them to inflict his twisted will on all of reality. Everything the Avengers have fought for has led up to this moment - the fate of Earth and existence itself has never been more uncertain.", - "poster_path": "https://image.tmdb.org/t/p/w500/7WsyChQLEftFiDOVTGkv3hFpyyt.jpg" - }, - { - "id": 299534, - "title": "Avengers: Endgame", - "tagline": "Part of the journey is the end.", - "overview": "After the devastating events of Avengers: Infinity War, the universe is in ruins due to the efforts of the Mad Titan, Thanos. With the help of remaining allies, the Avengers must assemble once more in order to undo Thanos' actions and restore order to the universe once and for all, no matter what consequences may be in store.", - "poster_path": "https://image.tmdb.org/t/p/w500/or06FN3Dka5tukK1e9sl16pB3iy.jpg" - }, - { - "id": 99861, - "title": "Avengers: Age of Ultron", - "tagline": "A New Age Has Come.", - "overview": "When Tony Stark tries to jumpstart a dormant peacekeeping program, things go awry and Earth’s Mightiest Heroes are put to the ultimate test as the fate of the planet hangs in the balance. As the villainous Ultron emerges, it is up to The Avengers to stop him from enacting his terrible plans, and soon uneasy alliances and unexpected action pave the way for an epic and unique global adventure.", - "poster_path": "https://image.tmdb.org/t/p/w500/t90Y3G8UGQp0f0DrP60wRu9gfrH.jpg" + let expected = json!([ + { + "title": "Captain Marvel", + "director": "Ryan Fleck", + "producer": "Kevin Feige", + "_formatted": { + "title": "Captain Marvel", + "director": "Ryan Fleck", + "producer": "Kevin Feige", + "overview": "1990s, Captain Marvel" } + } ]); - let (response, _status_code) = server.search(query); - assert_json_eq!(expect, response["hits"].clone(), ordered: false); + let (response, _status_code) = GLOBAL_SERVER.lock().unwrap().search(query); + assert_json_eq!(expected, response["hits"].clone(), ordered: false); } +// Search with attributes to highlight and matches and crop +// q: Captain +// limit: 1 +// attributesToRetrieve: [title,producer,director] +// attributesToCrop: [*,overview:10] +// attributesToHighlight: [*] #[test] -fn search_with_settings_searchable_attributes_2() { - let mut server = common::Server::with_uid("movies"); - server.populate_movies(); +fn search_with_differents_attributes_7() { + let query = "q=captain&limit=1&attributesToRetrieve=title,producer,director&attributesToCrop=*,overview:10&attributesToHighlight=*"; - let config = json!({ - "rankingRules": [ - "typo", - "words", - "proximity", - "attribute", - "wordsPosition", - "desc(popularity)", - "exactness", - "desc(vote_average)" - ], - "distinctAttribute": null, - "searchableAttributes": [ - "tagline", - "overview", - "title", - "cast", - "director", - "producer", - "production_companies", - "genres" - ], - "displayedAttributes": [ - "title", - "tagline", - "id", - "overview", - "poster_path" - ], - "stopWords": null, - "synonyms": null, - "acceptNewFields": false, - }); - - server.update_all_settings(config); - - let query = "q=avangers&limit=3"; - let expect = json!([ - { - "id": 299536, - "title": "Avengers: Infinity War", - "tagline": "An entire universe. Once and for all.", - "overview": "As the Avengers and their allies have continued to protect the world from threats too large for any one hero to handle, a new danger has emerged from the cosmic shadows: Thanos. A despot of intergalactic infamy, his goal is to collect all six Infinity Stones, artifacts of unimaginable power, and use them to inflict his twisted will on all of reality. Everything the Avengers have fought for has led up to this moment - the fate of Earth and existence itself has never been more uncertain.", - "poster_path": "https://image.tmdb.org/t/p/w500/7WsyChQLEftFiDOVTGkv3hFpyyt.jpg" - }, - { - "id": 299534, - "title": "Avengers: Endgame", - "tagline": "Part of the journey is the end.", - "overview": "After the devastating events of Avengers: Infinity War, the universe is in ruins due to the efforts of the Mad Titan, Thanos. With the help of remaining allies, the Avengers must assemble once more in order to undo Thanos' actions and restore order to the universe once and for all, no matter what consequences may be in store.", - "poster_path": "https://image.tmdb.org/t/p/w500/or06FN3Dka5tukK1e9sl16pB3iy.jpg" - }, - { - "id": 100402, - "title": "Captain America: The Winter Soldier", - "tagline": "In heroes we trust.", - "overview": "After the cataclysmic events in New York with The Avengers, Steve Rogers, aka Captain America is living quietly in Washington, D.C. and trying to adjust to the modern world. But when a S.H.I.E.L.D. colleague comes under attack, Steve becomes embroiled in a web of intrigue that threatens to put the world at risk. Joining forces with the Black Widow, Captain America struggles to expose the ever-widening conspiracy while fighting off professional assassins sent to silence him at every turn. When the full scope of the villainous plot is revealed, Captain America and the Black Widow enlist the help of a new ally, the Falcon. However, they soon find themselves up against an unexpected and formidable enemy—the Winter Soldier.", - "poster_path": "https://image.tmdb.org/t/p/w500/5TQ6YDmymBpnF005OyoB7ohZps9.jpg" + let expected = json!([ + { + "title": "Captain Marvel", + "director": "Ryan Fleck", + "producer": "Kevin Feige", + "_formatted": { + "title": "Captain Marvel", + "director": "Ryan Fleck", + "producer": "Kevin Feige", + "overview": "1990s, Captain Marvel" } + } ]); - let (response, _status_code) = server.search(query); - assert_json_eq!(expect, response["hits"].clone(), ordered: false); + let (response, _status_code) = GLOBAL_SERVER.lock().unwrap().search(query); + assert_json_eq!(expected, response["hits"].clone(), ordered: false); +} + +// Search with attributes to highlight and matches and crop +// q: Captain +// limit: 1 +// attributesToRetrieve: [title,producer,director] +// attributesToCrop: [*,overview:10] +// attributesToHighlight: [*,tagline] +#[test] +fn search_with_differents_attributes_8() { + let query = "q=captain&limit=1&attributesToRetrieve=title,producer,director&attributesToCrop=*,overview:10&attributesToHighlight=*,tagline"; + + let expected = json!([ + { + "title": "Captain Marvel", + "director": "Ryan Fleck", + "producer": "Kevin Feige", + "_formatted": { + "title": "Captain Marvel", + "director": "Ryan Fleck", + "producer": "Kevin Feige", + "tagline": "Higher. Further. Faster.", + "overview": "1990s, Captain Marvel" + } + } + ]); + + let (response, _status_code) = GLOBAL_SERVER.lock().unwrap().search(query); + assert_json_eq!(expected, response["hits"].clone(), ordered: false); } diff --git a/meilisearch-http/tests/search_settings.rs b/meilisearch-http/tests/search_settings.rs new file mode 100644 index 000000000..1e5762d65 --- /dev/null +++ b/meilisearch-http/tests/search_settings.rs @@ -0,0 +1,679 @@ +use assert_json_diff::assert_json_eq; +use serde_json::json; +use std::convert::Into; + +mod common; + +#[test] +fn search_with_settings_basic() { + let mut server = common::Server::with_uid("movies"); + server.populate_movies(); + + let config = json!({ + "rankingRules": [ + "typo", + "words", + "proximity", + "attribute", + "wordsPosition", + "desc(popularity)", + "exactness", + "desc(vote_average)" + ], + "distinctAttribute": null, + "searchableAttributes": [ + "title", + "tagline", + "overview", + "cast", + "director", + "producer", + "production_companies", + "genres" + ], + "displayedAttributes": [ + "title", + "director", + "producer", + "tagline", + "genres", + "id", + "overview", + "vote_count", + "vote_average", + "poster_path", + "popularity" + ], + "stopWords": null, + "synonyms": null, + "acceptNewFields": false, + }); + + server.update_all_settings(config); + + let query = "q=the%20avangers&limit=3"; + let expect = json!([ + { + "id": 24428, + "popularity": 44.506, + "vote_average": 7.7, + "title": "The Avengers", + "tagline": "Some assembly required.", + "overview": "When an unexpected enemy emerges and threatens global safety and security, Nick Fury, director of the international peacekeeping agency known as S.H.I.E.L.D., finds himself in need of a team to pull the world back from the brink of disaster. Spanning the globe, a daring recruitment effort begins!", + "director": "Joss Whedon", + "producer": "Kevin Feige", + "genres": [ + "Science Fiction", + "Action", + "Adventure" + ], + "poster_path": "https://image.tmdb.org/t/p/w500/cezWGskPY5x7GaglTTRN4Fugfb8.jpg", + "vote_count": 21079 + }, + { + "id": 299534, + "popularity": 38.659, + "vote_average": 8.3, + "title": "Avengers: Endgame", + "tagline": "Part of the journey is the end.", + "overview": "After the devastating events of Avengers: Infinity War, the universe is in ruins due to the efforts of the Mad Titan, Thanos. With the help of remaining allies, the Avengers must assemble once more in order to undo Thanos' actions and restore order to the universe once and for all, no matter what consequences may be in store.", + "director": "Anthony Russo", + "producer": "Kevin Feige", + "genres": [ + "Adventure", + "Science Fiction", + "Action" + ], + "poster_path": "https://image.tmdb.org/t/p/w500/or06FN3Dka5tukK1e9sl16pB3iy.jpg", + "vote_count": 10497 + }, + { + "id": 299536, + "popularity": 65.013, + "vote_average": 8.3, + "title": "Avengers: Infinity War", + "tagline": "An entire universe. Once and for all.", + "overview": "As the Avengers and their allies have continued to protect the world from threats too large for any one hero to handle, a new danger has emerged from the cosmic shadows: Thanos. A despot of intergalactic infamy, his goal is to collect all six Infinity Stones, artifacts of unimaginable power, and use them to inflict his twisted will on all of reality. Everything the Avengers have fought for has led up to this moment - the fate of Earth and existence itself has never been more uncertain.", + "director": "Anthony Russo", + "producer": "Kevin Feige", + "genres": [ + "Adventure", + "Action", + "Science Fiction" + ], + "poster_path": "https://image.tmdb.org/t/p/w500/7WsyChQLEftFiDOVTGkv3hFpyyt.jpg", + "vote_count": 16056 + } + ]); + + let (response, _status_code) = server.search(query); + assert_json_eq!(expect, response["hits"].clone(), ordered: false); +} + +#[test] +fn search_with_settings_stop_words() { + let mut server = common::Server::with_uid("movies"); + server.populate_movies(); + + let config = json!({ + "rankingRules": [ + "typo", + "words", + "proximity", + "attribute", + "wordsPosition", + "desc(popularity)", + "exactness", + "desc(vote_average)" + ], + "distinctAttribute": null, + "searchableAttributes": [ + "title", + "tagline", + "overview", + "cast", + "director", + "producer", + "production_companies", + "genres" + ], + "displayedAttributes": [ + "title", + "director", + "producer", + "tagline", + "genres", + "id", + "overview", + "vote_count", + "vote_average", + "poster_path", + "popularity" + ], + "stopWords": ["the"], + "synonyms": null, + "acceptNewFields": false, + }); + + server.update_all_settings(config); + + let query = "q=the%20avangers&limit=3"; + let expect = json!([ + { + "id": 299536, + "popularity": 65.013, + "vote_average": 8.3, + "title": "Avengers: Infinity War", + "tagline": "An entire universe. Once and for all.", + "overview": "As the Avengers and their allies have continued to protect the world from threats too large for any one hero to handle, a new danger has emerged from the cosmic shadows: Thanos. A despot of intergalactic infamy, his goal is to collect all six Infinity Stones, artifacts of unimaginable power, and use them to inflict his twisted will on all of reality. Everything the Avengers have fought for has led up to this moment - the fate of Earth and existence itself has never been more uncertain.", + "director": "Anthony Russo", + "producer": "Kevin Feige", + "genres": [ + "Adventure", + "Action", + "Science Fiction" + ], + "poster_path": "https://image.tmdb.org/t/p/w500/7WsyChQLEftFiDOVTGkv3hFpyyt.jpg", + "vote_count": 16056 + }, + { + "id": 299534, + "popularity": 38.659, + "vote_average": 8.3, + "title": "Avengers: Endgame", + "tagline": "Part of the journey is the end.", + "overview": "After the devastating events of Avengers: Infinity War, the universe is in ruins due to the efforts of the Mad Titan, Thanos. With the help of remaining allies, the Avengers must assemble once more in order to undo Thanos' actions and restore order to the universe once and for all, no matter what consequences may be in store.", + "director": "Anthony Russo", + "producer": "Kevin Feige", + "genres": [ + "Adventure", + "Science Fiction", + "Action" + ], + "poster_path": "https://image.tmdb.org/t/p/w500/or06FN3Dka5tukK1e9sl16pB3iy.jpg", + "vote_count": 10497 + }, + { + "id": 99861, + "popularity": 33.938, + "vote_average": 7.3, + "title": "Avengers: Age of Ultron", + "tagline": "A New Age Has Come.", + "overview": "When Tony Stark tries to jumpstart a dormant peacekeeping program, things go awry and Earth’s Mightiest Heroes are put to the ultimate test as the fate of the planet hangs in the balance. As the villainous Ultron emerges, it is up to The Avengers to stop him from enacting his terrible plans, and soon uneasy alliances and unexpected action pave the way for an epic and unique global adventure.", + "director": "Joss Whedon", + "producer": "Kevin Feige", + "genres": [ + "Action", + "Adventure", + "Science Fiction" + ], + "poster_path": "https://image.tmdb.org/t/p/w500/t90Y3G8UGQp0f0DrP60wRu9gfrH.jpg", + "vote_count": 14661 + } + ]); + + let (response, _status_code) = server.search(query); + assert_json_eq!(expect, response["hits"].clone(), ordered: false); +} + +#[test] +fn search_with_settings_synonyms() { + let mut server = common::Server::with_uid("movies"); + server.populate_movies(); + + let config = json!({ + "rankingRules": [ + "typo", + "words", + "proximity", + "attribute", + "wordsPosition", + "desc(popularity)", + "exactness", + "desc(vote_average)" + ], + "distinctAttribute": null, + "searchableAttributes": [ + "title", + "tagline", + "overview", + "cast", + "director", + "producer", + "production_companies", + "genres" + ], + "displayedAttributes": [ + "title", + "director", + "producer", + "tagline", + "genres", + "id", + "overview", + "vote_count", + "vote_average", + "poster_path", + "popularity" + ], + "stopWords": null, + "synonyms": { + "avangers": [ + "Captain America", + "Iron Man" + ] + }, + "acceptNewFields": false, + }); + + server.update_all_settings(config); + + let query = "q=avangers&limit=3"; + let expect = json!([ + { + "id": 299536, + "popularity": 65.013, + "vote_average": 8.3, + "title": "Avengers: Infinity War", + "tagline": "An entire universe. Once and for all.", + "overview": "As the Avengers and their allies have continued to protect the world from threats too large for any one hero to handle, a new danger has emerged from the cosmic shadows: Thanos. A despot of intergalactic infamy, his goal is to collect all six Infinity Stones, artifacts of unimaginable power, and use them to inflict his twisted will on all of reality. Everything the Avengers have fought for has led up to this moment - the fate of Earth and existence itself has never been more uncertain.", + "director": "Anthony Russo", + "producer": "Kevin Feige", + "genres": [ + "Adventure", + "Action", + "Science Fiction" + ], + "vote_count": 16056, + "poster_path": "https://image.tmdb.org/t/p/w500/7WsyChQLEftFiDOVTGkv3hFpyyt.jpg" + }, + { + "id": 299534, + "popularity": 38.659, + "vote_average": 8.3, + "title": "Avengers: Endgame", + "tagline": "Part of the journey is the end.", + "overview": "After the devastating events of Avengers: Infinity War, the universe is in ruins due to the efforts of the Mad Titan, Thanos. With the help of remaining allies, the Avengers must assemble once more in order to undo Thanos' actions and restore order to the universe once and for all, no matter what consequences may be in store.", + "director": "Anthony Russo", + "producer": "Kevin Feige", + "genres": [ + "Adventure", + "Science Fiction", + "Action" + ], + "vote_count": 10497, + "poster_path": "https://image.tmdb.org/t/p/w500/or06FN3Dka5tukK1e9sl16pB3iy.jpg" + }, + { + "id": 99861, + "popularity": 33.938, + "vote_average": 7.3, + "title": "Avengers: Age of Ultron", + "tagline": "A New Age Has Come.", + "overview": "When Tony Stark tries to jumpstart a dormant peacekeeping program, things go awry and Earth’s Mightiest Heroes are put to the ultimate test as the fate of the planet hangs in the balance. As the villainous Ultron emerges, it is up to The Avengers to stop him from enacting his terrible plans, and soon uneasy alliances and unexpected action pave the way for an epic and unique global adventure.", + "director": "Joss Whedon", + "producer": "Kevin Feige", + "genres": [ + "Action", + "Adventure", + "Science Fiction" + ], + "vote_count": 14661, + "poster_path": "https://image.tmdb.org/t/p/w500/t90Y3G8UGQp0f0DrP60wRu9gfrH.jpg" + } + ]); + + let (response, _status_code) = server.search(query); + assert_json_eq!(expect, response["hits"].clone(), ordered: false); +} + +#[test] +fn search_with_settings_ranking_rules() { + let mut server = common::Server::with_uid("movies"); + server.populate_movies(); + + let config = json!({ + "rankingRules": [ + "typo", + "words", + "proximity", + "attribute", + "wordsPosition", + "asc(vote_average)", + "exactness", + "desc(popularity)" + ], + "distinctAttribute": null, + "searchableAttributes": [ + "title", + "tagline", + "overview", + "cast", + "director", + "producer", + "production_companies", + "genres" + ], + "displayedAttributes": [ + "title", + "director", + "producer", + "tagline", + "genres", + "id", + "overview", + "vote_count", + "vote_average", + "poster_path", + "popularity" + ], + "stopWords": null, + "synonyms": null, + "acceptNewFields": false, + }); + + server.update_all_settings(config); + + let query = "q=avangers&limit=3"; + let expect = json!([ + { + "id": 99861, + "popularity": 33.938, + "vote_average": 7.3, + "title": "Avengers: Age of Ultron", + "tagline": "A New Age Has Come.", + "overview": "When Tony Stark tries to jumpstart a dormant peacekeeping program, things go awry and Earth’s Mightiest Heroes are put to the ultimate test as the fate of the planet hangs in the balance. As the villainous Ultron emerges, it is up to The Avengers to stop him from enacting his terrible plans, and soon uneasy alliances and unexpected action pave the way for an epic and unique global adventure.", + "director": "Joss Whedon", + "producer": "Kevin Feige", + "genres": [ + "Action", + "Adventure", + "Science Fiction" + ], + "poster_path": "https://image.tmdb.org/t/p/w500/t90Y3G8UGQp0f0DrP60wRu9gfrH.jpg", + "vote_count": 14661 + }, + { + "id": 299536, + "popularity": 65.013, + "vote_average": 8.3, + "title": "Avengers: Infinity War", + "tagline": "An entire universe. Once and for all.", + "overview": "As the Avengers and their allies have continued to protect the world from threats too large for any one hero to handle, a new danger has emerged from the cosmic shadows: Thanos. A despot of intergalactic infamy, his goal is to collect all six Infinity Stones, artifacts of unimaginable power, and use them to inflict his twisted will on all of reality. Everything the Avengers have fought for has led up to this moment - the fate of Earth and existence itself has never been more uncertain.", + "director": "Anthony Russo", + "producer": "Kevin Feige", + "genres": [ + "Adventure", + "Action", + "Science Fiction" + ], + "poster_path": "https://image.tmdb.org/t/p/w500/7WsyChQLEftFiDOVTGkv3hFpyyt.jpg", + "vote_count": 16056 + }, + { + "id": 299534, + "popularity": 38.659, + "vote_average": 8.3, + "title": "Avengers: Endgame", + "tagline": "Part of the journey is the end.", + "overview": "After the devastating events of Avengers: Infinity War, the universe is in ruins due to the efforts of the Mad Titan, Thanos. With the help of remaining allies, the Avengers must assemble once more in order to undo Thanos' actions and restore order to the universe once and for all, no matter what consequences may be in store.", + "director": "Anthony Russo", + "producer": "Kevin Feige", + "genres": [ + "Adventure", + "Science Fiction", + "Action" + ], + "poster_path": "https://image.tmdb.org/t/p/w500/or06FN3Dka5tukK1e9sl16pB3iy.jpg", + "vote_count": 10497 + } + ]); + + let (response, _status_code) = server.search(query); + assert_json_eq!(expect, response["hits"].clone(), ordered: false); +} + +#[test] +fn search_with_settings_searchable_attributes() { + let mut server = common::Server::with_uid("movies"); + server.populate_movies(); + + let config = json!({ + "rankingRules": [ + "typo", + "words", + "proximity", + "attribute", + "wordsPosition", + "desc(popularity)", + "exactness", + "desc(vote_average)" + ], + "distinctAttribute": null, + "searchableAttributes": [ + "tagline", + "overview", + "cast", + "director", + "producer", + "production_companies", + "genres" + ], + "displayedAttributes": [ + "title", + "director", + "producer", + "tagline", + "genres", + "id", + "overview", + "vote_count", + "vote_average", + "poster_path", + "popularity" + ], + "stopWords": null, + "synonyms": null, + "acceptNewFields": false, + }); + + server.update_all_settings(config); + + let query = "q=avangers&limit=3"; + let expect = json!([ + { + "id": 299536, + "popularity": 65.013, + "vote_average": 8.3, + "title": "Avengers: Infinity War", + "tagline": "An entire universe. Once and for all.", + "overview": "As the Avengers and their allies have continued to protect the world from threats too large for any one hero to handle, a new danger has emerged from the cosmic shadows: Thanos. A despot of intergalactic infamy, his goal is to collect all six Infinity Stones, artifacts of unimaginable power, and use them to inflict his twisted will on all of reality. Everything the Avengers have fought for has led up to this moment - the fate of Earth and existence itself has never been more uncertain.", + "director": "Anthony Russo", + "producer": "Kevin Feige", + "genres": [ + "Adventure", + "Action", + "Science Fiction" + ], + "poster_path": "https://image.tmdb.org/t/p/w500/7WsyChQLEftFiDOVTGkv3hFpyyt.jpg", + "vote_count": 16056 + }, + { + "id": 299534, + "popularity": 38.659, + "vote_average": 8.3, + "title": "Avengers: Endgame", + "tagline": "Part of the journey is the end.", + "overview": "After the devastating events of Avengers: Infinity War, the universe is in ruins due to the efforts of the Mad Titan, Thanos. With the help of remaining allies, the Avengers must assemble once more in order to undo Thanos' actions and restore order to the universe once and for all, no matter what consequences may be in store.", + "director": "Anthony Russo", + "producer": "Kevin Feige", + "genres": [ + "Adventure", + "Science Fiction", + "Action" + ], + "poster_path": "https://image.tmdb.org/t/p/w500/or06FN3Dka5tukK1e9sl16pB3iy.jpg", + "vote_count": 10497 + }, + { + "id": 100402, + "popularity": 16.418, + "vote_average": 7.7, + "title": "Captain America: The Winter Soldier", + "tagline": "In heroes we trust.", + "overview": "After the cataclysmic events in New York with The Avengers, Steve Rogers, aka Captain America is living quietly in Washington, D.C. and trying to adjust to the modern world. But when a S.H.I.E.L.D. colleague comes under attack, Steve becomes embroiled in a web of intrigue that threatens to put the world at risk. Joining forces with the Black Widow, Captain America struggles to expose the ever-widening conspiracy while fighting off professional assassins sent to silence him at every turn. When the full scope of the villainous plot is revealed, Captain America and the Black Widow enlist the help of a new ally, the Falcon. However, they soon find themselves up against an unexpected and formidable enemy—the Winter Soldier.", + "director": "Anthony Russo", + "producer": "Kevin Feige", + "genres": [ + "Action", + "Adventure", + "Science Fiction" + ], + "poster_path": "https://image.tmdb.org/t/p/w500/5TQ6YDmymBpnF005OyoB7ohZps9.jpg", + "vote_count": 11972 + } + ]); + + let (response, _status_code) = server.search(query); + assert_json_eq!(expect, response["hits"].clone(), ordered: false); +} + +#[test] +fn search_with_settings_displayed_attributes() { + let mut server = common::Server::with_uid("movies"); + server.populate_movies(); + + let config = json!({ + "rankingRules": [ + "typo", + "words", + "proximity", + "attribute", + "wordsPosition", + "desc(popularity)", + "exactness", + "desc(vote_average)" + ], + "distinctAttribute": null, + "searchableAttributes": [ + "title", + "tagline", + "overview", + "cast", + "director", + "producer", + "production_companies", + "genres" + ], + "displayedAttributes": [ + "title", + "tagline", + "id", + "overview", + "poster_path" + ], + "stopWords": null, + "synonyms": null, + "acceptNewFields": false, + }); + + server.update_all_settings(config); + + let query = "q=avangers&limit=3"; + let expect = json!([ + { + "id": 299536, + "title": "Avengers: Infinity War", + "tagline": "An entire universe. Once and for all.", + "overview": "As the Avengers and their allies have continued to protect the world from threats too large for any one hero to handle, a new danger has emerged from the cosmic shadows: Thanos. A despot of intergalactic infamy, his goal is to collect all six Infinity Stones, artifacts of unimaginable power, and use them to inflict his twisted will on all of reality. Everything the Avengers have fought for has led up to this moment - the fate of Earth and existence itself has never been more uncertain.", + "poster_path": "https://image.tmdb.org/t/p/w500/7WsyChQLEftFiDOVTGkv3hFpyyt.jpg" + }, + { + "id": 299534, + "title": "Avengers: Endgame", + "tagline": "Part of the journey is the end.", + "overview": "After the devastating events of Avengers: Infinity War, the universe is in ruins due to the efforts of the Mad Titan, Thanos. With the help of remaining allies, the Avengers must assemble once more in order to undo Thanos' actions and restore order to the universe once and for all, no matter what consequences may be in store.", + "poster_path": "https://image.tmdb.org/t/p/w500/or06FN3Dka5tukK1e9sl16pB3iy.jpg" + }, + { + "id": 99861, + "title": "Avengers: Age of Ultron", + "tagline": "A New Age Has Come.", + "overview": "When Tony Stark tries to jumpstart a dormant peacekeeping program, things go awry and Earth’s Mightiest Heroes are put to the ultimate test as the fate of the planet hangs in the balance. As the villainous Ultron emerges, it is up to The Avengers to stop him from enacting his terrible plans, and soon uneasy alliances and unexpected action pave the way for an epic and unique global adventure.", + "poster_path": "https://image.tmdb.org/t/p/w500/t90Y3G8UGQp0f0DrP60wRu9gfrH.jpg" + } + ]); + + let (response, _status_code) = server.search(query); + assert_json_eq!(expect, response["hits"].clone(), ordered: false); +} + +#[test] +fn search_with_settings_searchable_attributes_2() { + let mut server = common::Server::with_uid("movies"); + server.populate_movies(); + + let config = json!({ + "rankingRules": [ + "typo", + "words", + "proximity", + "attribute", + "wordsPosition", + "desc(popularity)", + "exactness", + "desc(vote_average)" + ], + "distinctAttribute": null, + "searchableAttributes": [ + "tagline", + "overview", + "title", + "cast", + "director", + "producer", + "production_companies", + "genres" + ], + "displayedAttributes": [ + "title", + "tagline", + "id", + "overview", + "poster_path" + ], + "stopWords": null, + "synonyms": null, + "acceptNewFields": false, + }); + + server.update_all_settings(config); + + let query = "q=avangers&limit=3"; + let expect = json!([ + { + "id": 299536, + "title": "Avengers: Infinity War", + "tagline": "An entire universe. Once and for all.", + "overview": "As the Avengers and their allies have continued to protect the world from threats too large for any one hero to handle, a new danger has emerged from the cosmic shadows: Thanos. A despot of intergalactic infamy, his goal is to collect all six Infinity Stones, artifacts of unimaginable power, and use them to inflict his twisted will on all of reality. Everything the Avengers have fought for has led up to this moment - the fate of Earth and existence itself has never been more uncertain.", + "poster_path": "https://image.tmdb.org/t/p/w500/7WsyChQLEftFiDOVTGkv3hFpyyt.jpg" + }, + { + "id": 299534, + "title": "Avengers: Endgame", + "tagline": "Part of the journey is the end.", + "overview": "After the devastating events of Avengers: Infinity War, the universe is in ruins due to the efforts of the Mad Titan, Thanos. With the help of remaining allies, the Avengers must assemble once more in order to undo Thanos' actions and restore order to the universe once and for all, no matter what consequences may be in store.", + "poster_path": "https://image.tmdb.org/t/p/w500/or06FN3Dka5tukK1e9sl16pB3iy.jpg" + }, + { + "id": 100402, + "title": "Captain America: The Winter Soldier", + "tagline": "In heroes we trust.", + "overview": "After the cataclysmic events in New York with The Avengers, Steve Rogers, aka Captain America is living quietly in Washington, D.C. and trying to adjust to the modern world. But when a S.H.I.E.L.D. colleague comes under attack, Steve becomes embroiled in a web of intrigue that threatens to put the world at risk. Joining forces with the Black Widow, Captain America struggles to expose the ever-widening conspiracy while fighting off professional assassins sent to silence him at every turn. When the full scope of the villainous plot is revealed, Captain America and the Black Widow enlist the help of a new ally, the Falcon. However, they soon find themselves up against an unexpected and formidable enemy—the Winter Soldier.", + "poster_path": "https://image.tmdb.org/t/p/w500/5TQ6YDmymBpnF005OyoB7ohZps9.jpg" + } + ]); + + let (response, _status_code) = server.search(query); + assert_json_eq!(expect, response["hits"].clone(), ordered: false); +} From c6fb5913484216e12c0be1a1e6d986914f8c556b Mon Sep 17 00:00:00 2001 From: Quentin de Quelen Date: Thu, 9 Apr 2020 16:57:08 +0200 Subject: [PATCH 3/4] add * on attributesToRetrieve --- meilisearch-http/src/routes/search.rs | 21 +++++++++++++----- meilisearch-http/tests/search.rs | 32 +++++++++++++++++++++++++++ 2 files changed, 48 insertions(+), 5 deletions(-) diff --git a/meilisearch-http/src/routes/search.rs b/meilisearch-http/src/routes/search.rs index a3a90391c..4d547d268 100644 --- a/meilisearch-http/src/routes/search.rs +++ b/meilisearch-http/src/routes/search.rs @@ -58,8 +58,20 @@ pub async fn search_with_url_query(ctx: Request) -> SResult { let mut restricted_attributes: HashSet<&str>; match &query.attributes_to_retrieve { Some(attributes_to_retrieve) => { - restricted_attributes = attributes_to_retrieve.split(',').collect(); - restricted_attributes.retain(|attr| available_attributes.contains(attr)); + let attributes_to_retrieve: HashSet<&str> = attributes_to_retrieve.split(',').collect(); + if attributes_to_retrieve.contains("*") { + restricted_attributes = available_attributes.clone(); + } else { + restricted_attributes = HashSet::new(); + for attr in attributes_to_retrieve { + if available_attributes.contains(attr) { + restricted_attributes.insert(attr); + search_builder.add_retrievable_field(attr.to_string()); + } else { + warn!("The attributes {:?} present in attributesToCrop parameter doesn't exist", attr); + } + } + } }, None => { restricted_attributes = available_attributes.clone(); @@ -94,10 +106,9 @@ pub async fn search_with_url_query(ctx: Request) -> SResult { search_builder.attributes_to_crop(final_attributes); } - if let Some(inline_attributes) = query.attributes_to_highlight { + if let Some(attributes_to_highlight) = query.attributes_to_highlight { let mut final_attributes: HashSet = HashSet::new(); - - for attribute in inline_attributes.split(',') { + for attribute in attributes_to_highlight.split(',') { if attribute == "*" { for attr in &restricted_attributes { final_attributes.insert(attr.to_string()); diff --git a/meilisearch-http/tests/search.rs b/meilisearch-http/tests/search.rs index 174894f7a..6dbc9bc3e 100644 --- a/meilisearch-http/tests/search.rs +++ b/meilisearch-http/tests/search.rs @@ -458,6 +458,38 @@ fn search_with_attributes_to_retrieve() { assert_json_eq!(expected, response["hits"].clone(), ordered: false); } +// Search with attributes to retrieve wildcard +// q: Captain +// limit: 1 +// attributesToRetrieve: * +#[test] +fn search_with_attributes_to_retrieve_wildcard() { + let query = "q=captain&limit=1&attributesToRetrieve=*"; + + let expected = json!([ + { + "id": 299537, + "popularity": 44.726, + "vote_average": 7.0, + "title": "Captain Marvel", + "tagline": "Higher. Further. Faster.", + "overview": "The story follows Carol Danvers as she becomes one of the universe’s most powerful heroes when Earth is caught in the middle of a galactic war between two alien races. Set in the 1990s, Captain Marvel is an all-new adventure from a previously unseen period in the history of the Marvel Cinematic Universe.", + "director": "Ryan Fleck", + "producer": "Kevin Feige", + "genres": [ + "Action", + "Adventure", + "Science Fiction" + ], + "poster_path": "https://image.tmdb.org/t/p/w500/AtsgWhDnHTq68L0lLsUrCnM7TjG.jpg", + "vote_count": 7858 + } + ]); + + let (response, _status_code) = GLOBAL_SERVER.lock().unwrap().search(query); + assert_json_eq!(expected, response["hits"].clone(), ordered: false); +} + // Search with filter // q: Captain // limit: 1 From 233651bef8c0e846226325df93840dc401eab1a9 Mon Sep 17 00:00:00 2001 From: Quentin de Quelen Date: Fri, 3 Apr 2020 16:17:09 +0200 Subject: [PATCH 4/4] update changelog --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4e9c82f1d..b4e58e3f3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,3 +10,4 @@ - Fixed a bug where the result of the update status after the first update was empty (#542) - Fixed a bug where stop words were not handled correctly (#594) - Fix CORS issues (#602) + - Support wildcard on attributes to retrieve, highlight, and crop (#549, #565, and #598)