diff --git a/crates/milli/src/search/new/mod.rs b/crates/milli/src/search/new/mod.rs index e22883839..dec307d31 100644 --- a/crates/milli/src/search/new/mod.rs +++ b/crates/milli/src/search/new/mod.rs @@ -21,7 +21,7 @@ mod vector_sort; #[cfg(test)] mod tests; -use std::collections::HashSet; +use std::collections::{HashMap, HashSet}; use std::ops::AddAssign; use std::time::Duration; @@ -64,6 +64,12 @@ use crate::{ UserError, Weight, }; +/// Cache for synonyms to avoid repeated database access +#[derive(Default)] +pub struct SynonymCache { + pub cache: Option, Vec>>>, +} + /// A structure used throughout the execution of a search query. pub struct SearchContext<'ctx> { pub index: &'ctx Index, @@ -73,6 +79,7 @@ pub struct SearchContext<'ctx> { pub phrase_interner: DedupInterner, pub term_interner: Interner, pub phrase_docids: PhraseDocIdsCache, + pub synonym_cache: SynonymCache, pub restricted_fids: Option, pub prefix_search: PrefixSearch, pub vector_store_stats: Option, @@ -103,6 +110,7 @@ impl<'ctx> SearchContext<'ctx> { phrase_interner: <_>::default(), term_interner: <_>::default(), phrase_docids: <_>::default(), + synonym_cache: <_>::default(), restricted_fids: None, prefix_search, vector_store_stats: None, @@ -113,6 +121,17 @@ impl<'ctx> SearchContext<'ctx> { self.prefix_search != PrefixSearch::Disabled } + /// Get synonyms with caching to avoid repeated database access + pub fn get_synonyms(&mut self) -> Result<&HashMap, Vec>>> { + match self.synonym_cache.cache { + Some(ref synonyms) => Ok(synonyms), + None => { + let synonyms = self.index.synonyms(self.txn)?; + Ok(self.synonym_cache.cache.insert(synonyms)) + } + } + } + pub fn attributes_to_search_on( &mut self, attributes_to_search_on: &'ctx [String], diff --git a/crates/milli/src/search/new/query_term/compute_derivations.rs b/crates/milli/src/search/new/query_term/compute_derivations.rs index dcb68f2ea..7761bd319 100644 --- a/crates/milli/src/search/new/query_term/compute_derivations.rs +++ b/crates/milli/src/search/new/query_term/compute_derivations.rs @@ -214,7 +214,7 @@ pub fn partially_initialized_term_from_word( if is_prefix && use_prefix_db.is_none() { find_zero_typo_prefix_derivations(ctx, word_interned, &mut prefix_of)?; } - let synonyms = ctx.index.synonyms(ctx.txn)?; + let synonyms = ctx.get_synonyms()?; let mut synonym_word_count = 0; let synonyms = synonyms .get(&vec![word.to_owned()]) diff --git a/crates/milli/src/search/new/query_term/parse_query.rs b/crates/milli/src/search/new/query_term/parse_query.rs index 64bbb94c0..ee9241e75 100644 --- a/crates/milli/src/search/new/query_term/parse_query.rs +++ b/crates/milli/src/search/new/query_term/parse_query.rs @@ -258,7 +258,7 @@ pub fn make_ngram( partially_initialized_term_from_word(ctx, &ngram_str, max_nbr_typos, is_prefix, true)?; // Now add the synonyms - let index_synonyms = ctx.index.synonyms(ctx.txn)?; + let index_synonyms = ctx.get_synonyms()?; term.zero_typo.synonyms.extend( index_synonyms.get(&words).cloned().unwrap_or_default().into_iter().map(|words| {