diff --git a/meilisearch-core/src/settings.rs b/meilisearch-core/src/settings.rs index b9ec0fa3e..05e6117f0 100644 --- a/meilisearch-core/src/settings.rs +++ b/meilisearch-core/src/settings.rs @@ -31,6 +31,8 @@ pub struct Settings { pub synonyms: Option>>>, #[serde(default, deserialize_with = "deserialize_some")] pub accept_new_fields: Option>, + #[serde(default, deserialize_with = "deserialize_some")] + pub attributes_for_faceting: Option>>, } // Any value that is present is considered Some value, including null. @@ -60,6 +62,7 @@ impl Settings { stop_words: settings.stop_words.into(), synonyms: settings.synonyms.into(), accept_new_fields: settings.accept_new_fields.into(), + attributes_for_faceting: settings.attributes_for_faceting.into(), }) } } @@ -166,6 +169,7 @@ pub struct SettingsUpdate { pub stop_words: UpdateState>, pub synonyms: UpdateState>>, pub accept_new_fields: UpdateState, + pub attributes_for_faceting: UpdateState>, } impl Default for SettingsUpdate { @@ -179,6 +183,7 @@ impl Default for SettingsUpdate { stop_words: UpdateState::Nothing, synonyms: UpdateState::Nothing, accept_new_fields: UpdateState::Nothing, + attributes_for_faceting: UpdateState::Nothing, } } } diff --git a/meilisearch-core/src/update/settings_update.rs b/meilisearch-core/src/update/settings_update.rs index 0ad2c904d..b4bf6c125 100644 --- a/meilisearch-core/src/update/settings_update.rs +++ b/meilisearch-core/src/update/settings_update.rs @@ -102,6 +102,18 @@ pub fn apply_settings_update( UpdateState::Nothing => (), } + match settings.attributes_for_faceting { + UpdateState::Update(attrs) => { + apply_attributes_for_faceting_update(writer, index, &mut schema, &attrs)?; + must_reindex = true; + }, + UpdateState::Clear => { + index.main.delete_attributes_for_faceting(writer)?; + index.facets.clear(writer)?; + }, + UpdateState::Nothing => (), + } + index.main.put_schema(writer, &schema)?; match settings.stop_words { @@ -131,6 +143,21 @@ pub fn apply_settings_update( Ok(()) } +fn apply_attributes_for_faceting_update( + writer: &mut heed::RwTxn, + index: &store::Index, + schema: &mut Schema, + attributes: &[String] + ) -> MResult<()> { + let mut attribute_ids = Vec::new(); + for name in attributes { + attribute_ids.push(schema.insert(name)?); + } + let attributes_for_faceting = SetBuf::from_dirty(attribute_ids); + index.main.put_attributes_for_faceting(writer, &attributes_for_faceting)?; + Ok(()) +} + pub fn apply_stop_words_update( writer: &mut heed::RwTxn, index: &store::Index, diff --git a/meilisearch-http/src/routes/setting.rs b/meilisearch-http/src/routes/setting.rs index 262af8b84..96e6935e7 100644 --- a/meilisearch-http/src/routes/setting.rs +++ b/meilisearch-http/src/routes/setting.rs @@ -91,6 +91,17 @@ async fn get_all( let schema = index.main.schema(&reader)?; + let attributes_for_faceting = match (&schema, &index.main.attributes_for_faceting(&reader)?) { + (Some(schema), Some(attrs)) => { + Some(attrs + .iter() + .filter_map(|&id| schema .name(id)) + .map(str::to_string) + .collect()) + } + _ => None, + }; + let searchable_attributes = schema.clone().map(|s| { s.indexed_name() .iter() @@ -115,6 +126,7 @@ async fn get_all( stop_words: Some(Some(stop_words)), synonyms: Some(Some(synonyms)), accept_new_fields: Some(accept_new_fields), + attributes_for_faceting: Some(attributes_for_faceting), }; Ok(HttpResponse::Ok().json(settings)) @@ -140,6 +152,7 @@ async fn delete_all( stop_words: UpdateState::Clear, synonyms: UpdateState::Clear, accept_new_fields: UpdateState::Clear, + attributes_for_faceting: UpdateState::Clear, }; let update_id = index.settings_update(&mut writer, settings)?; diff --git a/meilisearch-http/tests/settings.rs b/meilisearch-http/tests/settings.rs index 63f91da56..ad2d8caab 100644 --- a/meilisearch-http/tests/settings.rs +++ b/meilisearch-http/tests/settings.rs @@ -8,7 +8,6 @@ mod common; async fn write_all_and_delete() { let mut server = common::Server::with_uid("movies"); server.populate_movies().await; - // 2 - Send the settings let body = json!({ @@ -48,9 +47,11 @@ async fn write_all_and_delete() { "wolverine": ["xmen", "logan"], "logan": ["wolverine"], }, + "attributesForFaceting": ["title"], "acceptNewFields": false, }); + server.update_all_settings(body.clone()).await; // 3 - Get all settings and compare to the previous one @@ -119,6 +120,7 @@ async fn write_all_and_delete() { ], "stopWords": [], "synonyms": {}, + "attributesForFaceting": null, "acceptNewFields": true, }); @@ -169,6 +171,7 @@ async fn write_all_and_update() { "wolverine": ["xmen", "logan"], "logan": ["wolverine"], }, + "attributesForFaceting": ["title"], "acceptNewFields": false, }); @@ -210,6 +213,7 @@ async fn write_all_and_update() { "wolverine": ["xmen", "logan"], "logan": ["wolverine", "xmen"], }, + "attributesForFaceting": ["title"], "acceptNewFields": false, }); @@ -247,6 +251,7 @@ async fn write_all_and_update() { "wolverine": ["xmen", "logan"], "logan": ["wolverine", "xmen"], }, + "attributesForFaceting": ["title"], "acceptNewFields": false }); @@ -277,6 +282,7 @@ async fn test_default_settings() { "displayedAttributes": [], "stopWords": [], "synonyms": {}, + "attributesForFaceting": null, "acceptNewFields": true, }); @@ -314,6 +320,7 @@ async fn test_default_settings_2() { ], "stopWords": [], "synonyms": {}, + "attributesForFaceting": null, "acceptNewFields": true, }); @@ -421,6 +428,7 @@ async fn write_setting_and_update_partial() { "wolverine": ["xmen", "logan"], "logan": ["wolverine"], }, + "attributesForFaceting": null, "acceptNewFields": false, });