diff --git a/milli/src/fieldids_weights_map.rs b/milli/src/fieldids_weights_map.rs index 72720a02a..5ca2a6146 100644 --- a/milli/src/fieldids_weights_map.rs +++ b/milli/src/fieldids_weights_map.rs @@ -4,7 +4,7 @@ use std::collections::HashMap; use serde::{Deserialize, Serialize}; -use crate::{FieldId, Weight}; +use crate::{FieldId, FieldsIdsMap, Weight}; #[derive(Debug, Default, Serialize, Deserialize)] pub struct FieldidsWeightsMap { @@ -19,6 +19,13 @@ impl FieldidsWeightsMap { self.map.insert(fid, weight) } + /// Create the map from the fields ids maps. + /// Should only be called in the case there are NO searchable attributes. + /// The weights and the fields ids will have the same values. + pub fn from_field_id_map_without_searchable(fid_map: &FieldsIdsMap) -> Self { + FieldidsWeightsMap { map: fid_map.ids().map(|fid| (fid, fid)).collect() } + } + /// Removes a field id from the map, returning the associated weight previously in the map. pub fn remove(&mut self, fid: FieldId) -> Option { self.map.remove(&fid) diff --git a/milli/src/index.rs b/milli/src/index.rs index c565cdd5b..36f0b339e 100644 --- a/milli/src/index.rs +++ b/milli/src/index.rs @@ -436,11 +436,20 @@ impl Index { /// Get the fieldids weights map which associates the field ids to their weights pub fn fieldids_weights_map(&self, rtxn: &RoTxn) -> heed::Result { - Ok(self - .main + self.main .remap_types::>() .get(rtxn, main_key::FIELDIDS_WEIGHTS_MAP_KEY)? - .unwrap_or_default()) + .map(Ok) + .unwrap_or_else(|| { + Ok(FieldidsWeightsMap::from_field_id_map_without_searchable( + &self.fields_ids_map(rtxn)?, + )) + }) + } + + /// Delete the fieldsids weights map + pub fn delete_fieldids_weights_map(&self, wtxn: &mut RwTxn) -> heed::Result { + self.main.remap_key_type::().delete(wtxn, main_key::FIELDIDS_WEIGHTS_MAP_KEY) } pub fn searchable_fields_and_weights<'a>( @@ -629,29 +638,13 @@ impl Index { pub(crate) fn put_all_searchable_fields_from_fields_ids_map( &self, wtxn: &mut RwTxn, - user_fields: Option<&[&str]>, + user_fields: &[&str], fields_ids_map: &FieldsIdsMap, ) -> Result<()> { - // Special case if there is no user defined fields. - // Then the whole field id map is marked as searchable. - if user_fields.is_none() { - let mut weights = self.fieldids_weights_map(wtxn)?; - let mut searchable = Vec::new(); - for (weight, (fid, name)) in fields_ids_map.iter().enumerate() { - searchable.push(name); - weights.insert(fid, weight as u16); - } - self.put_searchable_fields(wtxn, &searchable)?; - self.put_fieldids_weights_map(wtxn, &weights)?; - return Ok(()); - } - - let user_fields = user_fields.unwrap(); - // We can write the user defined searchable fields as-is. self.put_user_defined_searchable_fields(wtxn, user_fields)?; - let mut weights = self.fieldids_weights_map(wtxn)?; + let mut weights = FieldidsWeightsMap::default(); // Now we generate the real searchable fields: // 1. Take the user defined searchable fields as-is to keep the priority defined by the attributes criterion. @@ -682,6 +675,7 @@ impl Index { pub(crate) fn delete_all_searchable_fields(&self, wtxn: &mut RwTxn) -> heed::Result { let did_delete_searchable = self.delete_searchable_fields(wtxn)?; let did_delete_user_defined = self.delete_user_defined_searchable_fields(wtxn)?; + self.delete_fieldids_weights_map(wtxn)?; Ok(did_delete_searchable || did_delete_user_defined) } diff --git a/milli/src/update/settings.rs b/milli/src/update/settings.rs index c66148813..046644dc4 100644 --- a/milli/src/update/settings.rs +++ b/milli/src/update/settings.rs @@ -490,7 +490,7 @@ impl<'a, 't, 'i> Settings<'a, 't, 'i> { self.index.put_all_searchable_fields_from_fields_ids_map( self.wtxn, - Some(&names), + &names, &fields_ids_map, )?; self.index.put_fields_ids_map(self.wtxn, &fields_ids_map)?; @@ -1228,11 +1228,13 @@ impl InnerIndexSettings { .map(|searchable| searchable.iter().map(|s| s.as_str()).collect::>()); // in case new fields were introduced we're going to recreate the searchable fields. - index.put_all_searchable_fields_from_fields_ids_map( - wtxn, - searchable_fields.as_deref(), - &self.fields_ids_map, - )?; + if let Some(searchable_fields) = searchable_fields { + index.put_all_searchable_fields_from_fields_ids_map( + wtxn, + &searchable_fields, + &self.fields_ids_map, + )?; + } let searchable_fields_ids = index.searchable_fields_ids(wtxn)?; self.searchable_fields_ids = searchable_fields_ids; @@ -1513,7 +1515,7 @@ mod tests { use crate::error::Error; use crate::index::tests::TempIndex; use crate::update::ClearDocuments; - use crate::{Criterion, Filter, SearchResult}; + use crate::{db_snap, Criterion, Filter, SearchResult}; #[test] fn set_and_reset_searchable_fields() { @@ -1542,6 +1544,17 @@ mod tests { wtxn.commit().unwrap(); + db_snap!(index, fields_ids_map, @r###" + 0 id | + 1 name | + 2 age | + "###); + db_snap!(index, searchable_fields, @r###"["name"]"###); + db_snap!(index, fieldids_weights_map, @r###" + fid weight + 1 0 | + "###); + // Check that the searchable field is correctly set to "name" only. let rtxn = index.read_txn().unwrap(); // When we search for something that is not in @@ -1565,6 +1578,19 @@ mod tests { }) .unwrap(); + db_snap!(index, fields_ids_map, @r###" + 0 id | + 1 name | + 2 age | + "###); + db_snap!(index, searchable_fields, @r###"["id", "name", "age"]"###); + db_snap!(index, fieldids_weights_map, @r###" + fid weight + 0 0 | + 1 1 | + 2 2 | + "###); + // Check that the searchable field have been reset and documents are found now. let rtxn = index.read_txn().unwrap(); let fid_map = index.fields_ids_map(&rtxn).unwrap();