mirror of
				https://github.com/meilisearch/meilisearch.git
				synced 2025-10-30 23:46:28 +00:00 
			
		
		
		
	Replace the panicking expect by tracked Errors
This commit is contained in:
		| @@ -7,7 +7,7 @@ use heed::{Database, PolyDatabase, RoTxn, RwTxn}; | ||||
| use heed::types::*; | ||||
| use roaring::RoaringBitmap; | ||||
|  | ||||
| use crate::error::UserError; | ||||
| use crate::error::{UserError, FieldIdMapMissingEntry, InternalError}; | ||||
| use crate::{Criterion, default_criteria, FacetDistribution, FieldsDistribution, Search}; | ||||
| use crate::{BEU32, DocumentId, ExternalDocumentsIds, FieldId, Result}; | ||||
| use crate::{ | ||||
| @@ -304,14 +304,25 @@ impl Index { | ||||
|         self.main.get::<_, Str, SerdeBincode<Vec<&'t str>>>(rtxn, main_key::DISPLAYED_FIELDS_KEY) | ||||
|     } | ||||
|  | ||||
|     pub fn displayed_fields_ids(&self, rtxn: &RoTxn) -> heed::Result<Option<Vec<FieldId>>> { | ||||
|         let fields_ids_map = self.fields_ids_map(rtxn)?; | ||||
|         let ids = self.displayed_fields(rtxn)? | ||||
|             .map(|fields| fields | ||||
|                 .into_iter() | ||||
|                 .map(|name| fields_ids_map.id(name).expect("Field not found")) | ||||
|                 .collect::<Vec<_>>()); | ||||
|         Ok(ids) | ||||
|     /// Identical to `displayed_fields`, but returns the ids instead. | ||||
|     pub fn displayed_fields_ids(&self, rtxn: &RoTxn) -> Result<Option<Vec<FieldId>>> { | ||||
|         match self.displayed_fields(rtxn)? { | ||||
|             Some(fields) => { | ||||
|                 let fields_ids_map = self.fields_ids_map(rtxn)?; | ||||
|                 let mut fields_ids = Vec::new(); | ||||
|                 for name in fields.into_iter() { | ||||
|                     match fields_ids_map.id(name) { | ||||
|                         Some(field_id) => fields_ids.push(field_id), | ||||
|                         None => return Err(FieldIdMapMissingEntry::FieldName { | ||||
|                             field_name: name.to_string(), | ||||
|                             process: "Index::displayed_fields_ids", | ||||
|                         }.into()), | ||||
|                     } | ||||
|                 } | ||||
|                 Ok(Some(fields_ids)) | ||||
|             }, | ||||
|             None => Ok(None), | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     /* searchable fields */ | ||||
| @@ -333,20 +344,22 @@ impl Index { | ||||
|     } | ||||
|  | ||||
|     /// Identical to `searchable_fields`, but returns the ids instead. | ||||
|     pub fn searchable_fields_ids(&self, rtxn: &RoTxn) -> heed::Result<Option<Vec<FieldId>>> { | ||||
|     pub fn searchable_fields_ids(&self, rtxn: &RoTxn) -> Result<Option<Vec<FieldId>>> { | ||||
|         match self.searchable_fields(rtxn)? { | ||||
|             Some(names) => { | ||||
|                 let fields_map = self.fields_ids_map(rtxn)?; | ||||
|                 let mut ids = Vec::new(); | ||||
|                 for name in names { | ||||
|                     let id = fields_map | ||||
|                         .id(name) | ||||
|                         .ok_or_else(|| format!("field id map must contain {:?}", name)) | ||||
|                         .expect("corrupted data: "); | ||||
|                     ids.push(id); | ||||
|             Some(fields) => { | ||||
|                 let fields_ids_map = self.fields_ids_map(rtxn)?; | ||||
|                 let mut fields_ids = Vec::new(); | ||||
|                 for name in fields { | ||||
|                     match fields_ids_map.id(name) { | ||||
|                         Some(field_id) => fields_ids.push(field_id), | ||||
|                         None => return Err(FieldIdMapMissingEntry::FieldName { | ||||
|                             field_name: name.to_string(), | ||||
|                             process: "Index::searchable_fields_ids", | ||||
|                         }.into()), | ||||
|                     } | ||||
|                 } | ||||
|                 Ok(Some(ids)) | ||||
|             } | ||||
|                 Ok(Some(fields_ids)) | ||||
|             }, | ||||
|             None => Ok(None), | ||||
|         } | ||||
|     } | ||||
| @@ -371,21 +384,25 @@ impl Index { | ||||
|         )?.unwrap_or_default()) | ||||
|     } | ||||
|  | ||||
|     /// Same as `filterable_fields`, but returns ids instead. | ||||
|     pub fn filterable_fields_ids(&self, rtxn: &RoTxn) -> heed::Result<HashSet<FieldId>> { | ||||
|         let filterable_fields = self.filterable_fields(rtxn)?; | ||||
|     /// Identical to `filterable_fields`, but returns ids instead. | ||||
|     pub fn filterable_fields_ids(&self, rtxn: &RoTxn) -> Result<HashSet<FieldId>> { | ||||
|         let fields = self.filterable_fields(rtxn)?; | ||||
|         let fields_ids_map = self.fields_ids_map(rtxn)?; | ||||
|         let filterable_fields = filterable_fields | ||||
|             .iter() | ||||
|             .map(|k| { | ||||
|                 fields_ids_map | ||||
|                     .id(k) | ||||
|                     .ok_or_else(|| format!("{:?} should be present in the field id map", k)) | ||||
|                     .expect("corrupted data: ") | ||||
|             }) | ||||
|             .collect(); | ||||
|  | ||||
|         Ok(filterable_fields) | ||||
|         let mut fields_ids = HashSet::new(); | ||||
|         for name in fields { | ||||
|             match fields_ids_map.id(&name) { | ||||
|                 Some(field_id) => { | ||||
|                     fields_ids.insert(field_id); | ||||
|                 }, | ||||
|                 None => return Err(FieldIdMapMissingEntry::FieldName { | ||||
|                     field_name: name, | ||||
|                     process: "Index::filterable_fields_ids", | ||||
|                 }.into()), | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         Ok(fields_ids) | ||||
|     } | ||||
|  | ||||
|     /* faceted documents ids */ | ||||
| @@ -393,7 +410,7 @@ impl Index { | ||||
|     /// Returns the faceted fields names. | ||||
|     /// | ||||
|     /// Faceted fields are the union of all the filterable, distinct, and Asc/Desc fields. | ||||
|     pub fn faceted_fields(&self, rtxn: &RoTxn) -> heed::Result<HashSet<String>> { | ||||
|     pub fn faceted_fields(&self, rtxn: &RoTxn) -> Result<HashSet<String>> { | ||||
|         let filterable_fields = self.filterable_fields(rtxn)?; | ||||
|         let distinct_field = self.distinct_field(rtxn)?; | ||||
|         let asc_desc_fields = self.criteria(rtxn)? | ||||
| @@ -412,21 +429,25 @@ impl Index { | ||||
|         Ok(faceted_fields) | ||||
|     } | ||||
|  | ||||
|     /// Same as `faceted_fields`, but returns ids instead. | ||||
|     pub fn faceted_fields_ids(&self, rtxn: &RoTxn) -> heed::Result<HashSet<FieldId>> { | ||||
|         let faceted_fields = self.faceted_fields(rtxn)?; | ||||
|     /// Identical to `faceted_fields`, but returns ids instead. | ||||
|     pub fn faceted_fields_ids(&self, rtxn: &RoTxn) -> Result<HashSet<FieldId>> { | ||||
|         let fields = self.faceted_fields(rtxn)?; | ||||
|         let fields_ids_map = self.fields_ids_map(rtxn)?; | ||||
|         let faceted_fields = faceted_fields | ||||
|             .iter() | ||||
|             .map(|k| { | ||||
|                 fields_ids_map | ||||
|                     .id(k) | ||||
|                     .ok_or_else(|| format!("{:?} should be present in the field id map", k)) | ||||
|                     .expect("corrupted data: ") | ||||
|             }) | ||||
|             .collect(); | ||||
|  | ||||
|         Ok(faceted_fields) | ||||
|         let mut fields_ids = HashSet::new(); | ||||
|         for name in fields.into_iter() { | ||||
|             match fields_ids_map.id(&name) { | ||||
|                 Some(field_id) => { | ||||
|                     fields_ids.insert(field_id); | ||||
|                 }, | ||||
|                 None => return Err(FieldIdMapMissingEntry::FieldName { | ||||
|                     field_name: name, | ||||
|                     process: "Index::faceted_fields_ids", | ||||
|                 }.into()), | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         Ok(fields_ids) | ||||
|     } | ||||
|  | ||||
|     /* faceted documents ids */ | ||||
| @@ -651,19 +672,23 @@ impl Index { | ||||
|     } | ||||
|  | ||||
|     /// Returns the index creation time. | ||||
|     pub fn created_at(&self, rtxn: &RoTxn) -> heed::Result<DateTime<Utc>> { | ||||
|         let time = self.main | ||||
|     pub fn created_at(&self, rtxn: &RoTxn) -> Result<DateTime<Utc>> { | ||||
|         Ok(self.main | ||||
|             .get::<_, Str, SerdeJson<DateTime<Utc>>>(rtxn, main_key::CREATED_AT_KEY)? | ||||
|             .expect("Index without creation time"); | ||||
|         Ok(time) | ||||
|             .ok_or(InternalError::DatabaseMissingEntry { | ||||
|                 db_name: db_name::MAIN, | ||||
|                 key: Some(main_key::CREATED_AT_KEY), | ||||
|             })?) | ||||
|     } | ||||
|  | ||||
|     /// Returns the index last updated time. | ||||
|     pub fn updated_at(&self, rtxn: &RoTxn) -> heed::Result<DateTime<Utc>> { | ||||
|         let time = self.main | ||||
|     pub fn updated_at(&self, rtxn: &RoTxn) -> Result<DateTime<Utc>> { | ||||
|         Ok(self.main | ||||
|             .get::<_, Str, SerdeJson<DateTime<Utc>>>(rtxn, main_key::UPDATED_AT_KEY)? | ||||
|             .expect("Index without update time"); | ||||
|         Ok(time) | ||||
|             .ok_or(InternalError::DatabaseMissingEntry { | ||||
|                 db_name: db_name::MAIN, | ||||
|                 key: Some(main_key::UPDATED_AT_KEY), | ||||
|             })?) | ||||
|     } | ||||
|  | ||||
|     pub(crate) fn set_updated_at(&self, wtxn: &mut RwTxn, time: &DateTime<Utc>) -> heed::Result<()> { | ||||
|   | ||||
| @@ -76,7 +76,7 @@ pub trait Context<'c> { | ||||
|     fn word_position_iterator(&self, word: &str, level: TreeLevel, in_prefix_cache: bool, left: Option<u32>, right: Option<u32>) -> heed::Result<Box<dyn Iterator<Item =heed::Result<((&'c str, TreeLevel, u32, u32), RoaringBitmap)>> + 'c>>; | ||||
|     fn word_position_last_level(&self, word: &str, in_prefix_cache: bool) -> heed::Result<Option<TreeLevel>>; | ||||
|     fn synonyms(&self, word: &str) -> heed::Result<Option<Vec<Vec<String>>>>; | ||||
|     fn searchable_fields_ids(&self) ->  heed::Result<Vec<FieldId>>; | ||||
|     fn searchable_fields_ids(&self) ->  Result<Vec<FieldId>>; | ||||
|     fn field_id_word_count_docids(&self, field_id: FieldId, word_count: u8) -> heed::Result<Option<RoaringBitmap>>; | ||||
|     fn word_level_position_docids(&self, word: &str, level: TreeLevel, left: u32, right: u32) -> heed::Result<Option<RoaringBitmap>>; | ||||
| } | ||||
| @@ -174,7 +174,7 @@ impl<'c> Context<'c> for CriteriaBuilder<'c> { | ||||
|         self.index.words_synonyms(self.rtxn, &[word]) | ||||
|     } | ||||
|  | ||||
|     fn searchable_fields_ids(&self) -> heed::Result<Vec<FieldId>> { | ||||
|     fn searchable_fields_ids(&self) -> Result<Vec<FieldId>> { | ||||
|         match self.index.searchable_fields_ids(self.rtxn)? { | ||||
|             Some(searchable_fields_ids) => Ok(searchable_fields_ids), | ||||
|             None => Ok(self.index.fields_ids_map(self.rtxn)?.ids().collect()), | ||||
| @@ -478,7 +478,7 @@ pub mod test { | ||||
|             todo!() | ||||
|         } | ||||
|  | ||||
|         fn searchable_fields_ids(&self) ->  heed::Result<Vec<FieldId>> { | ||||
|         fn searchable_fields_ids(&self) ->  Result<Vec<FieldId>> { | ||||
|             todo!() | ||||
|         } | ||||
|  | ||||
|   | ||||
| @@ -3,9 +3,11 @@ use std::mem::size_of; | ||||
| use heed::types::ByteSlice; | ||||
| use roaring::RoaringBitmap; | ||||
|  | ||||
| use super::{Distinct, DocIter}; | ||||
| use crate::error::InternalError; | ||||
| use crate::heed_codec::facet::*; | ||||
| use crate::index::db_name; | ||||
| use crate::{DocumentId, FieldId, Index, Result}; | ||||
| use super::{Distinct, DocIter}; | ||||
|  | ||||
| const FID_SIZE: usize = size_of::<FieldId>(); | ||||
| const DOCID_SIZE: usize = size_of::<DocumentId>(); | ||||
| @@ -64,7 +66,10 @@ impl<'a> FacetDistinctIter<'a> { | ||||
|             let ((_, _, value), _) = item?; | ||||
|             let facet_docids = self | ||||
|                 .facet_string_docids(value)? | ||||
|                 .expect("Corrupted data: Facet values must exist"); | ||||
|                 .ok_or(InternalError::DatabaseMissingEntry { | ||||
|                     db_name: db_name::FACET_ID_STRING_DOCIDS, | ||||
|                     key: None, | ||||
|                 })?; | ||||
|             self.excluded.union_with(&facet_docids); | ||||
|         } | ||||
|  | ||||
| @@ -80,7 +85,10 @@ impl<'a> FacetDistinctIter<'a> { | ||||
|             let ((_, _, value), _) = item?; | ||||
|             let facet_docids = self | ||||
|                 .facet_number_docids(value)? | ||||
|                 .expect("Corrupted data: Facet values must exist"); | ||||
|                 .ok_or(InternalError::DatabaseMissingEntry { | ||||
|                     db_name: db_name::FACET_ID_F64_DOCIDS, | ||||
|                     key: None, | ||||
|                 })?; | ||||
|             self.excluded.union_with(&facet_docids); | ||||
|         } | ||||
|  | ||||
|   | ||||
| @@ -13,7 +13,7 @@ use meilisearch_tokenizer::{Analyzer, AnalyzerConfig}; | ||||
| use once_cell::sync::Lazy; | ||||
| use roaring::bitmap::RoaringBitmap; | ||||
|  | ||||
| use distinct::{Distinct, DocIter, FacetDistinct, NoopDistinct}; | ||||
| use crate::error::FieldIdMapMissingEntry; | ||||
| use crate::search::criteria::r#final::{Final, FinalResult}; | ||||
| use crate::{Index, DocumentId, Result}; | ||||
|  | ||||
| @@ -22,6 +22,8 @@ pub use self::matching_words::MatchingWords; | ||||
| pub(crate) use self::facet::ParserRule; | ||||
| use self::query_tree::QueryTreeBuilder; | ||||
|  | ||||
| use distinct::{Distinct, DocIter, FacetDistinct, NoopDistinct}; | ||||
|  | ||||
| // Building these factories is not free. | ||||
| static LEVDIST0: Lazy<LevBuilder> = Lazy::new(|| LevBuilder::new(0, true)); | ||||
| static LEVDIST1: Lazy<LevBuilder> = Lazy::new(|| LevBuilder::new(1, true)); | ||||
| @@ -142,7 +144,10 @@ impl<'a> Search<'a> { | ||||
|             None => self.perform_sort(NoopDistinct, matching_words, criteria), | ||||
|             Some(name) => { | ||||
|                 let field_ids_map = self.index.fields_ids_map(self.rtxn)?; | ||||
|                 let id = field_ids_map.id(name).expect("distinct not present in field map"); | ||||
|                 let id = field_ids_map.id(name).ok_or_else(|| FieldIdMapMissingEntry::FieldName { | ||||
|                     field_name: name.to_string(), | ||||
|                     process: "fetching distint attribute", | ||||
|                 })?; | ||||
|                 let distinct = FacetDistinct::new(id, self.index, self.rtxn); | ||||
|                 self.perform_sort(distinct, matching_words, criteria) | ||||
|             } | ||||
|   | ||||
| @@ -7,7 +7,7 @@ use heed::types::{ByteSlice, Unit}; | ||||
| use roaring::RoaringBitmap; | ||||
| use serde_json::Value; | ||||
|  | ||||
| use crate::error::{InternalError, UserError}; | ||||
| use crate::error::{InternalError, FieldIdMapMissingEntry, UserError}; | ||||
| use crate::heed_codec::CboRoaringBitmapCodec; | ||||
| use crate::index::{db_name, main_key}; | ||||
| use crate::{Index, DocumentId, FieldId, BEU32, SmallString32, ExternalDocumentsIds, Result}; | ||||
| @@ -84,7 +84,12 @@ impl<'t, 'u, 'i> DeleteDocuments<'t, 'u, 'i> { | ||||
|                 key: Some(main_key::PRIMARY_KEY_KEY), | ||||
|             } | ||||
|         })?; | ||||
|         let id_field = fields_ids_map.id(primary_key).expect(r#"the field "id" to be present"#); | ||||
|         let id_field = fields_ids_map.id(primary_key).ok_or_else(|| { | ||||
|             FieldIdMapMissingEntry::FieldName { | ||||
|                 field_name: primary_key.to_string(), | ||||
|                 process: "DeleteDocuments::execute", | ||||
|             } | ||||
|         })?; | ||||
|  | ||||
|         let Index { | ||||
|             env: _env, | ||||
|   | ||||
		Reference in New Issue
	
	Block a user