diff --git a/meilidb-core/src/criterion/mod.rs b/meilidb-core/src/criterion/mod.rs index 9b2962bdb..6ce42007c 100644 --- a/meilidb-core/src/criterion/mod.rs +++ b/meilidb-core/src/criterion/mod.rs @@ -113,7 +113,7 @@ impl<'a> Default for Criteria<'a> { } } -impl<'a> AsRef<[Box]> for Criteria<'a> { +impl<'a> AsRef<[Box]> for Criteria<'a> { fn as_ref(&self) -> &[Box] { &self.inner } diff --git a/meilidb-core/src/query_builder.rs b/meilidb-core/src/query_builder.rs index c7641e764..e11ec4535 100644 --- a/meilidb-core/src/query_builder.rs +++ b/meilidb-core/src/query_builder.rs @@ -37,8 +37,10 @@ fn generate_automatons(query: &str, store: &S) -> Result) { + let word = word.to_lowercase(); let alternatives = self.alternatives.entry(word.as_bytes().to_vec()).or_default(); let new = sdset_into_fstset(&new); *alternatives = set_from_stream(alternatives.op().add(new.into_stream()).r#union()); @@ -641,4 +644,47 @@ mod tests { }); assert_matches!(iter.next(), None); } + + /// Unique word has multi-word synonyms + #[test] + fn multiword_synonyms() { + let mut store = InMemorySetStore::from_iter(vec![ + (&b"new"[..], &[doc_index(0, 0)][..]), + (&b"york"[..], &[doc_index(0, 1)][..]), + (&b"subway"[..], &[doc_index(0, 2)][..]), + ]); + + store.add_synonym("NY", SetBuf::from_dirty(vec!["NYC", "new york", "new york city"])); + store.add_synonym("NYC", SetBuf::from_dirty(vec!["NY", "new york", "new york city"])); + + let builder = QueryBuilder::new(&store); + let results = builder.query("NY subway", 0..20).unwrap(); + let mut iter = results.into_iter(); + + assert_matches!(iter.next(), Some(Document { id: DocumentId(0), matches }) => { + let mut iter = matches.into_iter(); + assert_matches!(iter.next(), Some(Match { query_index: 0, word_index: 0, .. })); // new + assert_matches!(iter.next(), Some(Match { query_index: 0, word_index: 0, .. })); // new + assert_matches!(iter.next(), Some(Match { query_index: 0, word_index: 1, .. })); // york + assert_matches!(iter.next(), Some(Match { query_index: 0, word_index: 1, .. })); // york + assert_matches!(iter.next(), Some(Match { query_index: 1, word_index: 2, .. })); // subway + assert_matches!(iter.next(), None); + }); + assert_matches!(iter.next(), None); + + let builder = QueryBuilder::new(&store); + let results = builder.query("NYC subway", 0..20).unwrap(); + let mut iter = results.into_iter(); + + assert_matches!(iter.next(), Some(Document { id: DocumentId(0), matches }) => { + let mut iter = matches.into_iter(); + assert_matches!(iter.next(), Some(Match { query_index: 0, word_index: 0, .. })); // new + assert_matches!(iter.next(), Some(Match { query_index: 0, word_index: 0, .. })); // new + assert_matches!(iter.next(), Some(Match { query_index: 0, word_index: 1, .. })); // york + assert_matches!(iter.next(), Some(Match { query_index: 0, word_index: 1, .. })); // york + assert_matches!(iter.next(), Some(Match { query_index: 1, word_index: 2, .. })); // subway + assert_matches!(iter.next(), None); + }); + assert_matches!(iter.next(), None); + } }