diff --git a/CHANGELOG.md b/CHANGELOG.md index b6571c523..c96dd0a02 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,7 @@ ## v0.14.0 + - Sort displayedAttributes (#943) - Fix facet distribution case (#797) - Snapshotting (#839) - Fix bucket-sort unwrap bug (#915) diff --git a/meilisearch-core/src/database.rs b/meilisearch-core/src/database.rs index 44d3e331c..e8f3c7408 100644 --- a/meilisearch-core/src/database.rs +++ b/meilisearch-core/src/database.rs @@ -1,4 +1,5 @@ use std::collections::hash_map::{Entry, HashMap}; +use std::collections::BTreeMap; use std::fs::File; use std::path::Path; use std::sync::{Arc, RwLock}; @@ -577,7 +578,7 @@ impl Database { } // convert attributes to their names - let frequency: HashMap<_, _> = fields_frequency + let frequency: BTreeMap<_, _> = fields_frequency .into_iter() .filter_map(|(a, c)| schema.name(a).map(|name| (name.to_string(), c))) .collect(); diff --git a/meilisearch-core/src/settings.rs b/meilisearch-core/src/settings.rs index 456b9fead..50ac9c92c 100644 --- a/meilisearch-core/src/settings.rs +++ b/meilisearch-core/src/settings.rs @@ -1,4 +1,4 @@ -use std::collections::{BTreeMap, BTreeSet, HashSet}; +use std::collections::{BTreeMap, BTreeSet}; use std::str::FromStr; use std::iter::IntoIterator; @@ -23,7 +23,7 @@ pub struct Settings { #[serde(default, deserialize_with = "deserialize_some")] pub searchable_attributes: Option>>, #[serde(default, deserialize_with = "deserialize_some")] - pub displayed_attributes: Option>>, + pub displayed_attributes: Option>>, #[serde(default, deserialize_with = "deserialize_some")] pub stop_words: Option>>, #[serde(default, deserialize_with = "deserialize_some")] @@ -161,7 +161,7 @@ pub struct SettingsUpdate { pub distinct_attribute: UpdateState, pub primary_key: UpdateState, pub searchable_attributes: UpdateState>, - pub displayed_attributes: UpdateState>, + pub displayed_attributes: UpdateState>, pub stop_words: UpdateState>, pub synonyms: UpdateState>>, pub attributes_for_faceting: UpdateState>, diff --git a/meilisearch-core/src/store/main.rs b/meilisearch-core/src/store/main.rs index cf74e0698..5accdfbc7 100644 --- a/meilisearch-core/src/store/main.rs +++ b/meilisearch-core/src/store/main.rs @@ -1,5 +1,5 @@ use std::borrow::Cow; -use std::collections::HashMap; +use std::collections::BTreeMap; use chrono::{DateTime, Utc}; use heed::types::{ByteSlice, OwnedType, SerdeBincode, Str, CowSlice}; @@ -31,7 +31,7 @@ const SYNONYMS_KEY: &str = "synonyms"; const UPDATED_AT_KEY: &str = "updated-at"; const WORDS_KEY: &str = "words"; -pub type FreqsMap = HashMap; +pub type FreqsMap = BTreeMap; type SerdeFreqsMap = SerdeBincode; type SerdeDatetime = SerdeBincode>; diff --git a/meilisearch-http/src/routes/setting.rs b/meilisearch-http/src/routes/setting.rs index 77067d9dd..9e8bb8031 100644 --- a/meilisearch-http/src/routes/setting.rs +++ b/meilisearch-http/src/routes/setting.rs @@ -1,4 +1,4 @@ -use std::collections::{BTreeMap, BTreeSet, HashSet}; +use std::collections::{BTreeMap, BTreeSet}; use actix_web::{delete, get, post}; use actix_web::{web, HttpResponse}; @@ -405,7 +405,7 @@ async fn get_displayed( async fn update_displayed( data: web::Data, path: web::Path, - body: web::Json>>, + body: web::Json>>, ) -> Result { let index = data .db @@ -539,7 +539,7 @@ fn get_indexed_attributes(schema: &Schema) -> Vec { } } -fn get_displayed_attributes(schema: &Schema) -> HashSet { +fn get_displayed_attributes(schema: &Schema) -> BTreeSet { if schema.is_displayed_all() { ["*"].iter().map(|s| s.to_string()).collect() } else { diff --git a/meilisearch-http/src/routes/stats.rs b/meilisearch-http/src/routes/stats.rs index e05a5aedf..f8c531732 100644 --- a/meilisearch-http/src/routes/stats.rs +++ b/meilisearch-http/src/routes/stats.rs @@ -1,4 +1,4 @@ -use std::collections::HashMap; +use std::collections::{HashMap, BTreeMap}; use actix_web::web; use actix_web::HttpResponse; @@ -24,7 +24,7 @@ pub fn services(cfg: &mut web::ServiceConfig) { struct IndexStatsResponse { number_of_documents: u64, is_indexing: bool, - fields_distribution: HashMap, + fields_distribution: BTreeMap, } #[get("/indexes/{index_uid}/stats", wrap = "Authentication::Private")] diff --git a/meilisearch-http/tests/index.rs b/meilisearch-http/tests/index.rs index 29fbed070..ea66756a5 100644 --- a/meilisearch-http/tests/index.rs +++ b/meilisearch-http/tests/index.rs @@ -777,3 +777,33 @@ async fn update_existing_primary_key_is_error() { assert_eq!(response["errorCode"], "primary_key_already_present"); assert_eq!(response["errorType"], "invalid_request_error"); } + +#[actix_rt::test] +async fn test_facets_distribution_attribute() { + let mut server = common::Server::test_server().await; + + let (response, _status_code) = server.get_index_stats().await; + + let expected = json!({ + "isIndexing": false, + "numberOfDocuments":77, + "fieldsDistribution":{ + "age":77, + "gender":77, + "phone":77, + "name":77, + "registered":77, + "latitude":77, + "email":77, + "tags":77, + "longitude":77, + "color":77, + "address":77, + "balance":77, + "about":77, + "picture":77, + }, + }); + + assert_json_eq!(expected, response, ordered: true); +} \ No newline at end of file diff --git a/meilisearch-http/tests/settings.rs b/meilisearch-http/tests/settings.rs index 92114faa3..6b125c13a 100644 --- a/meilisearch-http/tests/settings.rs +++ b/meilisearch-http/tests/settings.rs @@ -468,3 +468,56 @@ async fn settings_that_contains_wildcard_is_wildcard() { assert_eq!(response["searchableAttributes"].as_array().unwrap()[0], "*"); assert_eq!(response["displayedAttributes"].as_array().unwrap()[0], "*"); } + +#[actix_rt::test] +async fn test_displayed_attributes_field() { + let mut server = common::Server::test_server().await; + + let body = json!({ + "rankingRules": [ + "typo", + "words", + "proximity", + "attribute", + "wordsPosition", + "exactness", + "desc(registered)", + "desc(age)", + ], + "distinctAttribute": "id", + "searchableAttributes": [ + "id", + "name", + "color", + "gender", + "email", + "phone", + "address", + "registered", + "about" + ], + "displayedAttributes": [ + "age", + "email", + "gender", + "name", + "registered", + ], + "stopWords": [ + "ad", + "in", + "ut", + ], + "synonyms": { + "road": ["avenue", "street"], + "street": ["avenue"], + }, + "attributesForFaceting": ["name"], + }); + + server.update_all_settings(body.clone()).await; + + let (response, _status_code) = server.get_all_settings().await; + + assert_json_eq!(body, response, ordered: true); +} \ No newline at end of file