diff --git a/meilidb-core/Cargo.toml b/meilidb-core/Cargo.toml index 9536df027..3c64717d4 100644 --- a/meilidb-core/Cargo.toml +++ b/meilidb-core/Cargo.toml @@ -44,8 +44,10 @@ git = "https://github.com/Kerollmops/fst.git" branch = "arc-byte-slice" [dev-dependencies] +assert_matches = "1.3" csv = "1.0.7" rustyline = { version = "5.0.0", default-features = false } structopt = "0.3.2" +tempfile = "3.1.0" termcolor = "1.0.4" toml = "0.5.3" diff --git a/meilidb-core/src/lib.rs b/meilidb-core/src/lib.rs index efc6ffee8..86162b20b 100644 --- a/meilidb-core/src/lib.rs +++ b/meilidb-core/src/lib.rs @@ -1,3 +1,6 @@ +#[cfg(test)] +#[macro_use] extern crate assert_matches; + mod automaton; mod database; mod error; diff --git a/meilidb-core/src/query_builder.rs b/meilidb-core/src/query_builder.rs index b488d17b0..d607393a4 100644 --- a/meilidb-core/src/query_builder.rs +++ b/meilidb-core/src/query_builder.rs @@ -278,3 +278,922 @@ impl<'a> QueryBuilder<'a> { Ok(documents) } } + +#[cfg(test)] +mod tests { + use super::*; + + use std::collections::{BTreeSet, HashMap}; + use std::iter::FromIterator; + + use fst::{Set, IntoStreamer}; + use sdset::SetBuf; + use tempfile::TempDir; + + use crate::DocIndex; + use crate::store::Index; + use crate::database::Database; + + const fn doc_index(document_id: u64, word_index: u16) -> DocIndex { + DocIndex { + document_id: DocumentId(document_id), + attribute: 0, + word_index, + char_index: 0, + char_length: 0, + } + } + + const fn doc_char_index(document_id: u64, word_index: u16, char_index: u16) -> DocIndex { + DocIndex { + document_id: DocumentId(document_id), + attribute: 0, + word_index, + char_index, + char_length: 0, + } + } + + pub struct TempDatabase { + database: Database, + index: Index, + tempdir: TempDir, + } + + impl TempDatabase { + pub fn query_builder(&self) -> QueryBuilder { + self.index.query_builder() + } + } + + impl<'a> FromIterator<(&'a str, &'a [DocIndex])> for TempDatabase { + fn from_iter>(iter: I) -> Self { + let tempdir = TempDir::new().unwrap(); + let database = Database::open_or_create(&tempdir).unwrap(); + let index = database.open_index("default").unwrap(); + + let rkv = database.rkv.read().unwrap(); + let mut writer = rkv.write().unwrap(); + + let mut words_fst = BTreeSet::new(); + let mut postings_lists = HashMap::new(); + + for (word, indexes) in iter { + let word = word.to_lowercase().into_bytes(); + words_fst.insert(word.clone()); + postings_lists.entry(word).or_insert_with(Vec::new).extend_from_slice(indexes); + } + + let words_fst = Set::from_iter(words_fst).unwrap(); + + index.main.put_words_fst(&mut writer, &words_fst).unwrap(); + + for (word, postings_list) in postings_lists { + let postings_list = SetBuf::from_dirty(postings_list); + index.postings_lists.put_postings_list(&mut writer, &word, &postings_list).unwrap(); + } + + writer.commit().unwrap(); + drop(rkv); + + TempDatabase { database, index, tempdir } + } + } + + #[test] + fn simple() { + let store = TempDatabase::from_iter(vec![ + ("iphone", &[doc_char_index(0, 0, 0)][..]), + ("from", &[doc_char_index(0, 1, 1)][..]), + ("apple", &[doc_char_index(0, 2, 2)][..]), + ]); + + let rkv = store.database.rkv.read().unwrap(); + let reader = rkv.read().unwrap(); + + let builder = store.query_builder(); + let results = builder.query(&reader, "iphone from apple", 0..20).unwrap(); + let mut iter = results.into_iter(); + + assert_matches!(iter.next(), Some(Document { id: DocumentId(0), matches, .. }) => { + let mut matches = matches.into_iter(); + assert_matches!(matches.next(), Some(TmpMatch { query_index: 0, word_index: 0, .. })); + assert_matches!(matches.next(), Some(TmpMatch { query_index: 1, word_index: 1, .. })); + assert_matches!(matches.next(), Some(TmpMatch { query_index: 2, word_index: 2, .. })); + assert_matches!(matches.next(), None); + }); + assert_matches!(iter.next(), None); + } + + // #[test] + // fn simple_synonyms() { + // let mut store = InMemorySetStore::from_iter(vec![ + // ("hello", &[doc_index(0, 0)][..]), + // ]); + + // store.add_synonym("bonjour", SetBuf::from_dirty(vec!["hello"])); + + // let builder = QueryBuilder::new(&store); + // let results = builder.query("hello", 0..20).unwrap(); + // let mut iter = results.into_iter(); + + // assert_matches!(iter.next(), Some(Document { id: DocumentId(0), matches, .. }) => { + // let mut matches = matches.into_iter(); + // assert_matches!(matches.next(), Some(TmpMatch { query_index: 0, word_index: 0, .. })); + // assert_matches!(matches.next(), None); + // }); + // assert_matches!(iter.next(), None); + + // let builder = QueryBuilder::new(&store); + // let results = builder.query("bonjour", 0..20).unwrap(); + // let mut iter = results.into_iter(); + + // assert_matches!(iter.next(), Some(Document { id: DocumentId(0), matches, .. }) => { + // let mut matches = matches.into_iter(); + // assert_matches!(matches.next(), Some(TmpMatch { query_index: 0, word_index: 0, .. })); + // assert_matches!(matches.next(), None); + // }); + // assert_matches!(iter.next(), None); + // } + + // #[test] + // fn prefix_synonyms() { + // let mut store = InMemorySetStore::from_iter(vec![ + // ("hello", &[doc_index(0, 0)][..]), + // ]); + + // store.add_synonym("bonjour", SetBuf::from_dirty(vec!["hello"])); + // store.add_synonym("salut", SetBuf::from_dirty(vec!["hello"])); + + // let builder = QueryBuilder::new(&store); + // let results = builder.query("sal", 0..20).unwrap(); + // let mut iter = results.into_iter(); + + // assert_matches!(iter.next(), Some(Document { id: DocumentId(0), matches, .. }) => { + // let mut matches = matches.into_iter(); + // assert_matches!(matches.next(), Some(TmpMatch { query_index: 0, word_index: 0, .. })); + // assert_matches!(matches.next(), None); + // }); + // assert_matches!(iter.next(), None); + + // let builder = QueryBuilder::new(&store); + // let results = builder.query("bonj", 0..20).unwrap(); + // let mut iter = results.into_iter(); + + // assert_matches!(iter.next(), Some(Document { id: DocumentId(0), matches, .. }) => { + // let mut matches = matches.into_iter(); + // assert_matches!(matches.next(), Some(TmpMatch { query_index: 0, word_index: 0, .. })); + // assert_matches!(matches.next(), None); + // }); + // assert_matches!(iter.next(), None); + + // let builder = QueryBuilder::new(&store); + // let results = builder.query("sal blabla", 0..20).unwrap(); + // let mut iter = results.into_iter(); + + // assert_matches!(iter.next(), None); + + // let builder = QueryBuilder::new(&store); + // let results = builder.query("bonj blabla", 0..20).unwrap(); + // let mut iter = results.into_iter(); + + // assert_matches!(iter.next(), None); + // } + + // #[test] + // fn levenshtein_synonyms() { + // let mut store = InMemorySetStore::from_iter(vec![ + // ("hello", &[doc_index(0, 0)][..]), + // ]); + + // store.add_synonym("salutation", SetBuf::from_dirty(vec!["hello"])); + + // let builder = QueryBuilder::new(&store); + // let results = builder.query("salutution", 0..20).unwrap(); + // let mut iter = results.into_iter(); + + // assert_matches!(iter.next(), Some(Document { id: DocumentId(0), matches, .. }) => { + // let mut matches = matches.into_iter(); + // assert_matches!(matches.next(), Some(TmpMatch { query_index: 0, word_index: 0, .. })); + // assert_matches!(matches.next(), None); + // }); + // assert_matches!(iter.next(), None); + + // let builder = QueryBuilder::new(&store); + // let results = builder.query("saluttion", 0..20).unwrap(); + // let mut iter = results.into_iter(); + + // assert_matches!(iter.next(), Some(Document { id: DocumentId(0), matches, .. }) => { + // let mut matches = matches.into_iter(); + // assert_matches!(matches.next(), Some(TmpMatch { query_index: 0, word_index: 0, .. })); + // assert_matches!(matches.next(), None); + // }); + // assert_matches!(iter.next(), None); + // } + + // #[test] + // fn harder_synonyms() { + // let mut store = InMemorySetStore::from_iter(vec![ + // ("hello", &[doc_index(0, 0)][..]), + // ("bonjour", &[doc_index(1, 3)]), + // ("salut", &[doc_index(2, 5)]), + // ]); + + // store.add_synonym("hello", SetBuf::from_dirty(vec!["bonjour", "salut"])); + // store.add_synonym("bonjour", SetBuf::from_dirty(vec!["hello", "salut"])); + // store.add_synonym("salut", SetBuf::from_dirty(vec!["hello", "bonjour"])); + + // let builder = QueryBuilder::new(&store); + // let results = builder.query("hello", 0..20).unwrap(); + // let mut iter = results.into_iter(); + + // assert_matches!(iter.next(), Some(Document { id: DocumentId(0), matches, .. }) => { + // let mut matches = matches.into_iter(); + // assert_matches!(matches.next(), Some(TmpMatch { query_index: 0, word_index: 0, .. })); + // assert_matches!(matches.next(), None); + // }); + // assert_matches!(iter.next(), Some(Document { id: DocumentId(1), matches, .. }) => { + // let mut matches = matches.into_iter(); + // assert_matches!(matches.next(), Some(TmpMatch { query_index: 0, word_index: 3, .. })); + // assert_matches!(matches.next(), None); + // }); + // assert_matches!(iter.next(), Some(Document { id: DocumentId(2), matches, .. }) => { + // let mut matches = matches.into_iter(); + // assert_matches!(matches.next(), Some(TmpMatch { query_index: 0, word_index: 5, .. })); + // assert_matches!(matches.next(), None); + // }); + // assert_matches!(iter.next(), None); + + // let builder = QueryBuilder::new(&store); + // let results = builder.query("bonjour", 0..20).unwrap(); + // let mut iter = results.into_iter(); + + // assert_matches!(iter.next(), Some(Document { id: DocumentId(0), matches, .. }) => { + // let mut matches = matches.into_iter(); + // assert_matches!(matches.next(), Some(TmpMatch { query_index: 0, word_index: 0, .. })); + // assert_matches!(matches.next(), None); + // }); + // assert_matches!(iter.next(), Some(Document { id: DocumentId(1), matches, .. }) => { + // let mut matches = matches.into_iter(); + // assert_matches!(matches.next(), Some(TmpMatch { query_index: 0, word_index: 3, .. })); + // assert_matches!(matches.next(), None); + // }); + // assert_matches!(iter.next(), Some(Document { id: DocumentId(2), matches, .. }) => { + // let mut matches = matches.into_iter(); + // assert_matches!(matches.next(), Some(TmpMatch { query_index: 0, word_index: 5, .. })); + // assert_matches!(matches.next(), None); + // }); + // assert_matches!(iter.next(), None); + + // let builder = QueryBuilder::new(&store); + // let results = builder.query("salut", 0..20).unwrap(); + // let mut iter = results.into_iter(); + + // assert_matches!(iter.next(), Some(Document { id: DocumentId(0), matches, .. }) => { + // let mut matches = matches.into_iter(); + // assert_matches!(matches.next(), Some(TmpMatch { query_index: 0, word_index: 0, .. })); + // assert_matches!(matches.next(), None); + // }); + // assert_matches!(iter.next(), Some(Document { id: DocumentId(1), matches, .. }) => { + // let mut matches = matches.into_iter(); + // assert_matches!(matches.next(), Some(TmpMatch { query_index: 0, word_index: 3, .. })); + // assert_matches!(matches.next(), None); + // }); + // assert_matches!(iter.next(), Some(Document { id: DocumentId(2), matches, .. }) => { + // let mut matches = matches.into_iter(); + // assert_matches!(matches.next(), Some(TmpMatch { query_index: 0, word_index: 5, .. })); + // assert_matches!(matches.next(), None); + // }); + // assert_matches!(iter.next(), None); + // } + + // #[test] + // /// Unique word has multi-word synonyms + // fn unique_to_multiword_synonyms() { + // let mut store = InMemorySetStore::from_iter(vec![ + // ("new", &[doc_char_index(0, 0, 0)][..]), + // ("york", &[doc_char_index(0, 1, 1)][..]), + // ("city", &[doc_char_index(0, 2, 2)][..]), + // ("subway", &[doc_char_index(0, 3, 3)][..]), + + // ("NY", &[doc_char_index(1, 0, 0)][..]), + // ("subway", &[doc_char_index(1, 1, 1)][..]), + // ]); + + // 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(1), matches, .. }) => { + // let mut iter = matches.into_iter(); + // assert_matches!(iter.next(), Some(TmpMatch { query_index: 0, word_index: 0, is_exact: true, .. })); // NY ± new + // assert_matches!(iter.next(), Some(TmpMatch { query_index: 1, word_index: 1, is_exact: true, .. })); // NY ± york + // assert_matches!(iter.next(), Some(TmpMatch { query_index: 2, word_index: 2, is_exact: true, .. })); // NY ± city + // assert_matches!(iter.next(), Some(TmpMatch { query_index: 3, word_index: 3, is_exact: true, .. })); // subway + // assert_matches!(iter.next(), None); + // }); + // assert_matches!(iter.next(), Some(Document { id: DocumentId(0), matches, .. }) => { + // let mut iter = matches.into_iter(); + // assert_matches!(iter.next(), Some(TmpMatch { query_index: 0, word_index: 0, is_exact: false, .. })); // new = NY + // assert_matches!(iter.next(), Some(TmpMatch { query_index: 0, word_index: 0, is_exact: false, .. })); // new = NY + // assert_matches!(iter.next(), Some(TmpMatch { query_index: 1, word_index: 1, is_exact: false, .. })); // york = NY + // assert_matches!(iter.next(), Some(TmpMatch { query_index: 1, word_index: 1, is_exact: false, .. })); // york = NY + // assert_matches!(iter.next(), Some(TmpMatch { query_index: 2, word_index: 2, is_exact: false, .. })); // city = NY + // assert_matches!(iter.next(), Some(TmpMatch { query_index: 2, word_index: 2, is_exact: false, .. })); // city = NY + // assert_matches!(iter.next(), Some(TmpMatch { query_index: 3, word_index: 3, is_exact: true, .. })); // subway + // assert_matches!(iter.next(), None); // position rewritten ^ + // }); + // 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(1), matches, .. }) => { + // let mut iter = matches.into_iter(); + // assert_matches!(iter.next(), Some(TmpMatch { query_index: 0, word_index: 0, is_exact: true, .. })); // NYC ± new + // assert_matches!(iter.next(), Some(TmpMatch { query_index: 1, word_index: 1, is_exact: true, .. })); // NYC ± york + // assert_matches!(iter.next(), Some(TmpMatch { query_index: 2, word_index: 2, is_exact: true, .. })); // NYC ± city + // assert_matches!(iter.next(), Some(TmpMatch { query_index: 3, word_index: 3, is_exact: true, .. })); // subway + // assert_matches!(iter.next(), None); + // }); + // assert_matches!(iter.next(), Some(Document { id: DocumentId(0), matches, .. }) => { + // let mut iter = matches.into_iter(); + // assert_matches!(iter.next(), Some(TmpMatch { query_index: 0, word_index: 0, is_exact: false, .. })); // new = NYC + // assert_matches!(iter.next(), Some(TmpMatch { query_index: 0, word_index: 0, is_exact: false, .. })); // new = NYC + // assert_matches!(iter.next(), Some(TmpMatch { query_index: 1, word_index: 1, is_exact: false, .. })); // york = NYC + // assert_matches!(iter.next(), Some(TmpMatch { query_index: 1, word_index: 1, is_exact: false, .. })); // york = NYC + // assert_matches!(iter.next(), Some(TmpMatch { query_index: 2, word_index: 2, is_exact: false, .. })); // city = NYC + // assert_matches!(iter.next(), Some(TmpMatch { query_index: 2, word_index: 2, is_exact: false, .. })); // city = NYC + // assert_matches!(iter.next(), Some(TmpMatch { query_index: 3, word_index: 3, is_exact: true, .. })); // subway + // assert_matches!(iter.next(), None); // position rewritten ^ + // }); + // assert_matches!(iter.next(), None); + // } + + // #[test] + // fn unique_to_multiword_synonyms_words_proximity() { + // let mut store = InMemorySetStore::from_iter(vec![ + // ("new", &[doc_char_index(0, 0, 0)][..]), + // ("york", &[doc_char_index(0, 1, 1)][..]), + // ("city", &[doc_char_index(0, 2, 2)][..]), + // ("subway", &[doc_char_index(0, 3, 3)][..]), + + // ("york", &[doc_char_index(1, 0, 0)][..]), + // ("new", &[doc_char_index(1, 1, 1)][..]), + // ("subway", &[doc_char_index(1, 2, 2)][..]), + + // ("NY", &[doc_char_index(2, 0, 0)][..]), + // ("subway", &[doc_char_index(2, 1, 1)][..]), + // ]); + + // store.add_synonym("NY", SetBuf::from_dirty(vec!["york new"])); + + // let builder = QueryBuilder::new(&store); + // let results = builder.query("NY", 0..20).unwrap(); + // let mut iter = results.into_iter(); + + // assert_matches!(iter.next(), Some(Document { id: DocumentId(2), matches, .. }) => { + // let mut matches = matches.into_iter(); + // assert_matches!(matches.next(), Some(TmpMatch { query_index: 0, word_index: 0, .. })); // NY ± york + // assert_matches!(matches.next(), Some(TmpMatch { query_index: 1, word_index: 1, .. })); // NY ± new + // assert_matches!(matches.next(), None); + // }); + // assert_matches!(iter.next(), Some(Document { id: DocumentId(1), matches, .. }) => { + // let mut matches = matches.into_iter(); + // assert_matches!(matches.next(), Some(TmpMatch { query_index: 0, word_index: 0, .. })); // york = NY + // assert_matches!(matches.next(), Some(TmpMatch { query_index: 1, word_index: 1, .. })); // new = NY + // assert_matches!(matches.next(), None); + // }); + // assert_matches!(iter.next(), Some(Document { id: DocumentId(0), matches, .. }) => { + // let mut matches = matches.into_iter(); + // assert_matches!(matches.next(), Some(TmpMatch { query_index: 0, word_index: 1, .. })); // york = NY + // assert_matches!(matches.next(), Some(TmpMatch { query_index: 1, word_index: 0, .. })); // new = NY + // assert_matches!(matches.next(), None); + // }); + // assert_matches!(iter.next(), None); + + // let builder = QueryBuilder::new(&store); + // let results = builder.query("new york", 0..20).unwrap(); + // let mut iter = results.into_iter(); + + // assert_matches!(iter.next(), Some(Document { id: DocumentId(0), matches, .. }) => { + // let mut matches = matches.into_iter(); + // assert_matches!(matches.next(), Some(TmpMatch { query_index: 0, word_index: 0, .. })); // new + // assert_matches!(matches.next(), Some(TmpMatch { query_index: 1, word_index: 1, .. })); // york + // assert_matches!(matches.next(), None); // position rewritten ^ + // }); + // assert_matches!(iter.next(), Some(Document { id: DocumentId(1), matches, .. }) => { + // let mut matches = matches.into_iter(); + // assert_matches!(matches.next(), Some(TmpMatch { query_index: 0, word_index: 1, .. })); // york + // assert_matches!(matches.next(), Some(TmpMatch { query_index: 1, word_index: 0, .. })); // new + // assert_matches!(matches.next(), None); + // }); + // assert_matches!(iter.next(), None); + // } + + // #[test] + // fn unique_to_multiword_synonyms_cumulative_word_index() { + // let mut store = InMemorySetStore::from_iter(vec![ + // ("NY", &[doc_char_index(0, 0, 0)][..]), + // ("subway", &[doc_char_index(0, 1, 1)][..]), + + // ("new", &[doc_char_index(1, 0, 0)][..]), + // ("york", &[doc_char_index(1, 1, 1)][..]), + // ("subway", &[doc_char_index(1, 2, 2)][..]), + // ]); + + // store.add_synonym("new york", SetBuf::from_dirty(vec!["NY"])); + + // 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 matches = matches.into_iter(); + // assert_matches!(matches.next(), Some(TmpMatch { query_index: 0, word_index: 0, is_exact: true, .. })); // NY + // assert_matches!(matches.next(), Some(TmpMatch { query_index: 1, word_index: 1, is_exact: true, .. })); // subway + // assert_matches!(matches.next(), None); + // }); + // assert_matches!(iter.next(), Some(Document { id: DocumentId(1), matches, .. }) => { + // let mut matches = matches.into_iter(); + // assert_matches!(matches.next(), Some(TmpMatch { query_index: 1, word_index: 2, is_exact: true, .. })); // subway + // assert_matches!(matches.next(), None); + // }); + // assert_matches!(iter.next(), None); + + // let builder = QueryBuilder::new(&store); + // let results = builder.query("new york subway", 0..20).unwrap(); + // let mut iter = results.into_iter(); + + // assert_matches!(iter.next(), Some(Document { id: DocumentId(0), matches, .. }) => { + // let mut matches = matches.into_iter(); + // assert_matches!(matches.next(), Some(TmpMatch { query_index: 0, word_index: 0, is_exact: true, .. })); // new = NY + // assert_matches!(matches.next(), Some(TmpMatch { query_index: 1, word_index: 1, is_exact: true, .. })); // york = NY + // assert_matches!(matches.next(), Some(TmpMatch { query_index: 2, word_index: 2, is_exact: true, .. })); // subway + // assert_matches!(matches.next(), None); + // }); + // assert_matches!(iter.next(), Some(Document { id: DocumentId(1), matches, .. }) => { + // let mut matches = matches.into_iter(); + // assert_matches!(matches.next(), Some(TmpMatch { query_index: 0, word_index: 0, is_exact: true, .. })); // new + // assert_matches!(matches.next(), Some(TmpMatch { query_index: 1, word_index: 1, is_exact: true, .. })); // york + // assert_matches!(matches.next(), Some(TmpMatch { query_index: 2, word_index: 2, is_exact: true, .. })); // subway + // assert_matches!(matches.next(), None); + // }); + // assert_matches!(iter.next(), None); + // } + + // #[test] + // /// Unique word has multi-word synonyms + // fn harder_unique_to_multiword_synonyms_one() { + // let mut store = InMemorySetStore::from_iter(vec![ + // ("new", &[doc_char_index(0, 0, 0)][..]), + // ("york", &[doc_char_index(0, 1, 1)][..]), + // ("city", &[doc_char_index(0, 2, 2)][..]), + // ("yellow", &[doc_char_index(0, 3, 3)][..]), + // ("subway", &[doc_char_index(0, 4, 4)][..]), + // ("broken", &[doc_char_index(0, 5, 5)][..]), + + // ("NY", &[doc_char_index(1, 0, 0)][..]), + // ("blue", &[doc_char_index(1, 1, 1)][..]), + // ("subway", &[doc_char_index(1, 2, 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(1), matches, .. }) => { + // let mut iter = matches.into_iter(); + // assert_matches!(iter.next(), Some(TmpMatch { query_index: 0, word_index: 0, is_exact: true, .. })); // new = NY + // assert_matches!(iter.next(), Some(TmpMatch { query_index: 1, word_index: 1, is_exact: true, .. })); // york = NY + // assert_matches!(iter.next(), Some(TmpMatch { query_index: 2, word_index: 2, is_exact: true, .. })); // city = NY + // assert_matches!(iter.next(), Some(TmpMatch { query_index: 3, word_index: 4, is_exact: true, .. })); // subway + // assert_matches!(iter.next(), None); // position rewritten ^ + // }); + // assert_matches!(iter.next(), Some(Document { id: DocumentId(0), matches, .. }) => { + // let mut iter = matches.into_iter(); + // assert_matches!(iter.next(), Some(TmpMatch { query_index: 0, word_index: 0, is_exact: false, .. })); // new = NY + // assert_matches!(iter.next(), Some(TmpMatch { query_index: 0, word_index: 0, is_exact: false, .. })); // new = NY + // assert_matches!(iter.next(), Some(TmpMatch { query_index: 1, word_index: 1, is_exact: false, .. })); // york = NY + // assert_matches!(iter.next(), Some(TmpMatch { query_index: 1, word_index: 1, is_exact: false, .. })); // york = NY + // assert_matches!(iter.next(), Some(TmpMatch { query_index: 2, word_index: 2, is_exact: false, .. })); // city = NY + // assert_matches!(iter.next(), Some(TmpMatch { query_index: 2, word_index: 2, is_exact: false, .. })); // city = NY + // assert_matches!(iter.next(), Some(TmpMatch { query_index: 3, word_index: 4, is_exact: true, .. })); // subway + // assert_matches!(iter.next(), None); // position rewritten ^ + // }); + // 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(1), matches, .. }) => { + // let mut iter = matches.into_iter(); + // assert_matches!(iter.next(), Some(TmpMatch { query_index: 0, word_index: 0, is_exact: true, .. })); // NYC + // assert_matches!(iter.next(), Some(TmpMatch { query_index: 1, word_index: 1, is_exact: true, .. })); // NYC + // assert_matches!(iter.next(), Some(TmpMatch { query_index: 2, word_index: 2, is_exact: true, .. })); // NYC + // // because one-word to one-word ^^^^ + // assert_matches!(iter.next(), Some(TmpMatch { query_index: 3, word_index: 4, is_exact: true, .. })); // subway + // assert_matches!(iter.next(), None); + // }); + // assert_matches!(iter.next(), Some(Document { id: DocumentId(0), matches, .. }) => { + // let mut iter = matches.into_iter(); + // assert_matches!(iter.next(), Some(TmpMatch { query_index: 0, word_index: 0, is_exact: false, .. })); // new = NYC + // assert_matches!(iter.next(), Some(TmpMatch { query_index: 0, word_index: 0, is_exact: false, .. })); // new = NYC + // assert_matches!(iter.next(), Some(TmpMatch { query_index: 1, word_index: 1, is_exact: false, .. })); // york = NYC + // assert_matches!(iter.next(), Some(TmpMatch { query_index: 1, word_index: 1, is_exact: false, .. })); // york = NYC + // assert_matches!(iter.next(), Some(TmpMatch { query_index: 2, word_index: 2, is_exact: false, .. })); // city = NYC + // assert_matches!(iter.next(), Some(TmpMatch { query_index: 2, word_index: 2, is_exact: false, .. })); // city = NYC + // assert_matches!(iter.next(), Some(TmpMatch { query_index: 3, word_index: 4, is_exact: true, .. })); // subway + // assert_matches!(iter.next(), None); // position rewritten ^ + // }); + // assert_matches!(iter.next(), None); + // } + + // #[test] + // /// Unique word has multi-word synonyms + // fn even_harder_unique_to_multiword_synonyms() { + // let mut store = InMemorySetStore::from_iter(vec![ + // ("new", &[doc_char_index(0, 0, 0)][..]), + // ("york", &[doc_char_index(0, 1, 1)][..]), + // ("city", &[doc_char_index(0, 2, 2)][..]), + // ("yellow", &[doc_char_index(0, 3, 3)][..]), + // ("underground", &[doc_char_index(0, 4, 4)][..]), + // ("train", &[doc_char_index(0, 5, 5)][..]), + // ("broken", &[doc_char_index(0, 6, 6)][..]), + + // ("NY", &[doc_char_index(1, 0, 0)][..]), + // ("blue", &[doc_char_index(1, 1, 1)][..]), + // ("subway", &[doc_char_index(1, 2, 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"])); + // store.add_synonym("subway", SetBuf::from_dirty(vec!["underground train"])); + + // let builder = QueryBuilder::new(&store); + // let results = builder.query("NY subway broken", 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(TmpMatch { query_index: 0, word_index: 0, is_exact: false, .. })); // new = NY + // assert_matches!(iter.next(), Some(TmpMatch { query_index: 0, word_index: 0, is_exact: false, .. })); // new = NY + // assert_matches!(iter.next(), Some(TmpMatch { query_index: 1, word_index: 1, is_exact: false, .. })); // york = NY + // assert_matches!(iter.next(), Some(TmpMatch { query_index: 1, word_index: 1, is_exact: false, .. })); // york = NY + // assert_matches!(iter.next(), Some(TmpMatch { query_index: 2, word_index: 2, is_exact: false, .. })); // city = NY + // assert_matches!(iter.next(), Some(TmpMatch { query_index: 2, word_index: 2, is_exact: false, .. })); // city = NY + // assert_matches!(iter.next(), Some(TmpMatch { query_index: 3, word_index: 4, is_exact: false, .. })); // underground = subway + // assert_matches!(iter.next(), Some(TmpMatch { query_index: 4, word_index: 5, is_exact: false, .. })); // train = subway + // assert_matches!(iter.next(), Some(TmpMatch { query_index: 5, word_index: 6, is_exact: true, .. })); // broken + // assert_matches!(iter.next(), None); // position rewritten ^ + // }); + // assert_matches!(iter.next(), Some(Document { id: DocumentId(1), matches, .. }) => { + // let mut iter = matches.into_iter(); + // assert_matches!(iter.next(), Some(TmpMatch { query_index: 0, word_index: 0, is_exact: true, .. })); // new = NY + // assert_matches!(iter.next(), Some(TmpMatch { query_index: 1, word_index: 1, is_exact: true, .. })); // york = NY + // assert_matches!(iter.next(), Some(TmpMatch { query_index: 2, word_index: 2, is_exact: true, .. })); // city = NY + // assert_matches!(iter.next(), Some(TmpMatch { query_index: 3, word_index: 4, is_exact: true, .. })); // underground = subway + // assert_matches!(iter.next(), Some(TmpMatch { query_index: 4, word_index: 5, is_exact: true, .. })); // train = subway + // assert_matches!(iter.next(), None); // position rewritten ^ + // }); + // 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(1), matches, .. }) => { + // let mut iter = matches.into_iter(); + // assert_matches!(iter.next(), Some(TmpMatch { query_index: 0, word_index: 0, is_exact: true, .. })); // new = NYC + // assert_matches!(iter.next(), Some(TmpMatch { query_index: 1, word_index: 1, is_exact: true, .. })); // york = NYC + // assert_matches!(iter.next(), Some(TmpMatch { query_index: 2, word_index: 2, is_exact: true, .. })); // city = NYC + // // because one-word to one-word ^^^^ + // assert_matches!(iter.next(), Some(TmpMatch { query_index: 3, word_index: 4, is_exact: true, .. })); // underground = subway + // assert_matches!(iter.next(), Some(TmpMatch { query_index: 4, word_index: 5, is_exact: true, .. })); // train = subway + // assert_matches!(iter.next(), None); + // }); + // assert_matches!(iter.next(), Some(Document { id: DocumentId(0), matches, .. }) => { + // let mut iter = matches.into_iter(); + // assert_matches!(iter.next(), Some(TmpMatch { query_index: 0, word_index: 0, is_exact: false, .. })); // new = NYC + // assert_matches!(iter.next(), Some(TmpMatch { query_index: 0, word_index: 0, is_exact: false, .. })); // new = NYC + // assert_matches!(iter.next(), Some(TmpMatch { query_index: 1, word_index: 1, is_exact: false, .. })); // york = NYC + // assert_matches!(iter.next(), Some(TmpMatch { query_index: 1, word_index: 1, is_exact: false, .. })); // york = NYC + // assert_matches!(iter.next(), Some(TmpMatch { query_index: 2, word_index: 2, is_exact: false, .. })); // city = NYC + // assert_matches!(iter.next(), Some(TmpMatch { query_index: 2, word_index: 2, is_exact: false, .. })); // city = NYC + // assert_matches!(iter.next(), Some(TmpMatch { query_index: 3, word_index: 4, is_exact: false, .. })); // underground = subway + // assert_matches!(iter.next(), Some(TmpMatch { query_index: 4, word_index: 5, is_exact: false, .. })); // train = subway + // assert_matches!(iter.next(), None); // position rewritten ^ + // }); + // assert_matches!(iter.next(), None); + // } + + // #[test] + // /// Multi-word has multi-word synonyms + // fn multiword_to_multiword_synonyms() { + // let mut store = InMemorySetStore::from_iter(vec![ + // ("NY", &[doc_char_index(0, 0, 0)][..]), + // ("subway", &[doc_char_index(0, 1, 1)][..]), + + // ("NYC", &[doc_char_index(1, 0, 0)][..]), + // ("blue", &[doc_char_index(1, 1, 1)][..]), + // ("subway", &[doc_char_index(1, 2, 2)][..]), + // ("broken", &[doc_char_index(1, 3, 3)][..]), + + // ("new", &[doc_char_index(2, 0, 0)][..]), + // ("york", &[doc_char_index(2, 1, 1)][..]), + // ("underground", &[doc_char_index(2, 2, 2)][..]), + // ("train", &[doc_char_index(2, 3, 3)][..]), + // ("broken", &[doc_char_index(2, 4, 4)][..]), + // ]); + + // store.add_synonym("new york", SetBuf::from_dirty(vec![ "NYC", "NY", "new york city" ])); + // store.add_synonym("new york city", SetBuf::from_dirty(vec![ "NYC", "NY", "new york" ])); + // store.add_synonym("underground train", SetBuf::from_dirty(vec![ "subway" ])); + + // let builder = QueryBuilder::new(&store); + // let results = builder.query("new york underground train broken", 0..20).unwrap(); + // let mut iter = results.into_iter(); + + // assert_matches!(iter.next(), Some(Document { id: DocumentId(2), matches, .. }) => { + // let mut matches = matches.into_iter(); + // assert_matches!(matches.next(), Some(TmpMatch { query_index: 0, word_index: 0, is_exact: false, .. })); // new + // assert_matches!(matches.next(), Some(TmpMatch { query_index: 0, word_index: 0, is_exact: true, .. })); // new + // assert_matches!(matches.next(), Some(TmpMatch { query_index: 1, word_index: 1, is_exact: false, .. })); // york + // assert_matches!(matches.next(), Some(TmpMatch { query_index: 1, word_index: 1, is_exact: true, .. })); // york + // assert_matches!(matches.next(), Some(TmpMatch { query_index: 2, word_index: 2, is_exact: true, .. })); // city + // assert_matches!(matches.next(), Some(TmpMatch { query_index: 3, word_index: 3, is_exact: true, .. })); // underground + // assert_matches!(matches.next(), Some(TmpMatch { query_index: 4, word_index: 4, is_exact: true, .. })); // train + // assert_matches!(matches.next(), Some(TmpMatch { query_index: 5, word_index: 5, is_exact: true, .. })); // broken + // assert_matches!(matches.next(), None); + // }); + // assert_matches!(iter.next(), Some(Document { id: DocumentId(1), matches, .. }) => { + // let mut iter = matches.into_iter(); + // assert_matches!(iter.next(), Some(TmpMatch { query_index: 0, word_index: 0, is_exact: true, .. })); // NYC = new + // assert_matches!(iter.next(), Some(TmpMatch { query_index: 1, word_index: 1, is_exact: true, .. })); // NYC = york + // assert_matches!(iter.next(), Some(TmpMatch { query_index: 2, word_index: 2, is_exact: true, .. })); // NYC = city + // assert_matches!(iter.next(), Some(TmpMatch { query_index: 3, word_index: 4, is_exact: true, .. })); // subway = underground + // assert_matches!(iter.next(), Some(TmpMatch { query_index: 4, word_index: 5, is_exact: true, .. })); // subway = train + // assert_matches!(iter.next(), Some(TmpMatch { query_index: 5, word_index: 6, is_exact: true, .. })); // broken + // assert_matches!(iter.next(), None); + // }); + // assert_matches!(iter.next(), Some(Document { id: DocumentId(0), matches, .. }) => { + // let mut iter = matches.into_iter(); + // assert_matches!(iter.next(), Some(TmpMatch { query_index: 0, word_index: 0, is_exact: true, .. })); // NY = new + // assert_matches!(iter.next(), Some(TmpMatch { query_index: 1, word_index: 1, is_exact: true, .. })); // NY = york + // assert_matches!(iter.next(), Some(TmpMatch { query_index: 2, word_index: 2, is_exact: true, .. })); // NY = city + // assert_matches!(iter.next(), Some(TmpMatch { query_index: 3, word_index: 3, is_exact: true, .. })); // subway = underground + // assert_matches!(iter.next(), Some(TmpMatch { query_index: 4, word_index: 4, is_exact: true, .. })); // subway = train + // assert_matches!(iter.next(), None); + // }); + // assert_matches!(iter.next(), None); + + // let builder = QueryBuilder::new(&store); + // let results = builder.query("new york city underground train broken", 0..20).unwrap(); + // let mut iter = results.into_iter(); + + // assert_matches!(iter.next(), Some(Document { id: DocumentId(2), matches, .. }) => { + // let mut matches = matches.into_iter(); + // assert_matches!(matches.next(), Some(TmpMatch { query_index: 0, word_index: 0, is_exact: false, .. })); // new + // assert_matches!(matches.next(), Some(TmpMatch { query_index: 0, word_index: 0, is_exact: false, .. })); // new + // assert_matches!(matches.next(), Some(TmpMatch { query_index: 0, word_index: 0, is_exact: true, .. })); // new + // assert_matches!(matches.next(), Some(TmpMatch { query_index: 1, word_index: 1, is_exact: false, .. })); // york + // assert_matches!(matches.next(), Some(TmpMatch { query_index: 1, word_index: 1, is_exact: false, .. })); // york + // assert_matches!(matches.next(), Some(TmpMatch { query_index: 1, word_index: 1, is_exact: true, .. })); // york + // assert_matches!(matches.next(), Some(TmpMatch { query_index: 2, word_index: 2, is_exact: false, .. })); // city + // assert_matches!(matches.next(), Some(TmpMatch { query_index: 3, word_index: 3, is_exact: true, .. })); // underground + // assert_matches!(matches.next(), Some(TmpMatch { query_index: 4, word_index: 4, is_exact: true, .. })); // train + // assert_matches!(matches.next(), Some(TmpMatch { query_index: 5, word_index: 5, is_exact: true, .. })); // broken + // assert_matches!(matches.next(), None); + // }); + // assert_matches!(iter.next(), Some(Document { id: DocumentId(1), matches, .. }) => { + // let mut iter = matches.into_iter(); + // assert_matches!(iter.next(), Some(TmpMatch { query_index: 0, word_index: 0, is_exact: true, .. })); // NYC = new + // assert_matches!(iter.next(), Some(TmpMatch { query_index: 0, word_index: 0, is_exact: true, .. })); // NYC = new + // assert_matches!(iter.next(), Some(TmpMatch { query_index: 1, word_index: 1, is_exact: true, .. })); // NYC = york + // assert_matches!(iter.next(), Some(TmpMatch { query_index: 1, word_index: 1, is_exact: true, .. })); // NYC = york + // assert_matches!(iter.next(), Some(TmpMatch { query_index: 2, word_index: 2, is_exact: true, .. })); // NYC = city + // assert_matches!(iter.next(), Some(TmpMatch { query_index: 3, word_index: 4, is_exact: true, .. })); // subway = underground + // assert_matches!(iter.next(), Some(TmpMatch { query_index: 4, word_index: 5, is_exact: true, .. })); // subway = train + // assert_matches!(iter.next(), Some(TmpMatch { query_index: 5, word_index: 6, is_exact: true, .. })); // broken + // assert_matches!(iter.next(), None); + // }); + // assert_matches!(iter.next(), Some(Document { id: DocumentId(0), matches, .. }) => { + // let mut iter = matches.into_iter(); + // assert_matches!(iter.next(), Some(TmpMatch { query_index: 0, word_index: 0, is_exact: true, .. })); // NY = new + // assert_matches!(iter.next(), Some(TmpMatch { query_index: 0, word_index: 0, is_exact: true, .. })); // NY = new + // assert_matches!(iter.next(), Some(TmpMatch { query_index: 1, word_index: 1, is_exact: true, .. })); // NY = york + // assert_matches!(iter.next(), Some(TmpMatch { query_index: 1, word_index: 1, is_exact: true, .. })); // NY = york + // assert_matches!(iter.next(), Some(TmpMatch { query_index: 2, word_index: 2, is_exact: true, .. })); // NY = city + // assert_matches!(iter.next(), Some(TmpMatch { query_index: 3, word_index: 3, is_exact: true, .. })); // subway = underground + // assert_matches!(iter.next(), Some(TmpMatch { query_index: 4, word_index: 4, is_exact: true, .. })); // subway = train + // assert_matches!(iter.next(), None); + // }); + // assert_matches!(iter.next(), None); + // } + + // #[test] + // fn intercrossed_multiword_synonyms() { + // let mut store = InMemorySetStore::from_iter(vec![ + // ("new", &[doc_index(0, 0)][..]), + // ("york", &[doc_index(0, 1)][..]), + // ("big", &[doc_index(0, 2)][..]), + // ("city", &[doc_index(0, 3)][..]), + // ]); + + // store.add_synonym("new york", SetBuf::from_dirty(vec![ "new york city" ])); + // store.add_synonym("new york city", SetBuf::from_dirty(vec![ "new york" ])); + + // let builder = QueryBuilder::new(&store); + // let results = builder.query("new york big ", 0..20).unwrap(); + // let mut iter = results.into_iter(); + + // assert_matches!(iter.next(), Some(Document { id: DocumentId(0), matches, .. }) => { + // let mut matches = matches.into_iter(); + // assert_matches!(matches.next(), Some(TmpMatch { query_index: 0, word_index: 0, is_exact: false, .. })); // new + // assert_matches!(matches.next(), Some(TmpMatch { query_index: 0, word_index: 0, is_exact: true, .. })); // new + + // assert_matches!(matches.next(), Some(TmpMatch { query_index: 1, word_index: 1, is_exact: false, .. })); // york + // assert_matches!(matches.next(), Some(TmpMatch { query_index: 1, word_index: 1, is_exact: true, .. })); // york + + // assert_matches!(matches.next(), Some(TmpMatch { query_index: 2, word_index: 2, is_exact: true, .. })); // city + // assert_matches!(matches.next(), Some(TmpMatch { query_index: 2, word_index: 4, is_exact: false, .. })); // city + + // assert_matches!(matches.next(), Some(TmpMatch { query_index: 3, word_index: 3, is_exact: true, .. })); // big + // assert_matches!(matches.next(), None); + // }); + // assert_matches!(iter.next(), None); + + // let mut store = InMemorySetStore::from_iter(vec![ + // ("NY", &[doc_index(0, 0)][..]), + // ("city", &[doc_index(0, 1)][..]), + // ("subway", &[doc_index(0, 2)][..]), + + // ("NY", &[doc_index(1, 0)][..]), + // ("subway", &[doc_index(1, 1)][..]), + + // ("NY", &[doc_index(2, 0)][..]), + // ("york", &[doc_index(2, 1)][..]), + // ("city", &[doc_index(2, 2)][..]), + // ("subway", &[doc_index(2, 3)][..]), + // ]); + + // store.add_synonym("NY", SetBuf::from_dirty(vec!["new york city story"])); + + // 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(1), matches, .. }) => { + // let mut matches = matches.into_iter(); + // assert_matches!(matches.next(), Some(TmpMatch { query_index: 0, word_index: 0, is_exact: true, .. })); // new + // assert_matches!(matches.next(), Some(TmpMatch { query_index: 1, word_index: 1, is_exact: true, .. })); // york + // assert_matches!(matches.next(), Some(TmpMatch { query_index: 2, word_index: 2, is_exact: true, .. })); // city + // assert_matches!(matches.next(), Some(TmpMatch { query_index: 3, word_index: 3, is_exact: true, .. })); // story + // assert_matches!(matches.next(), Some(TmpMatch { query_index: 4, word_index: 4, is_exact: true, .. })); // subway + // assert_matches!(matches.next(), None); + // }); + // assert_matches!(iter.next(), Some(Document { id: DocumentId(0), matches, .. }) => { + // let mut matches = matches.into_iter(); + // assert_matches!(matches.next(), Some(TmpMatch { query_index: 0, word_index: 0, is_exact: true, .. })); // new + // assert_matches!(matches.next(), Some(TmpMatch { query_index: 1, word_index: 1, is_exact: true, .. })); // york + // assert_matches!(matches.next(), Some(TmpMatch { query_index: 2, word_index: 2, is_exact: false, .. })); // city + // assert_matches!(matches.next(), Some(TmpMatch { query_index: 2, word_index: 2, is_exact: true, .. })); // city + // assert_matches!(matches.next(), Some(TmpMatch { query_index: 4, word_index: 3, is_exact: true, .. })); // subway + // assert_matches!(matches.next(), None); + // }); + // assert_matches!(iter.next(), Some(Document { id: DocumentId(2), matches, .. }) => { + // let mut matches = matches.into_iter(); + // assert_matches!(matches.next(), Some(TmpMatch { query_index: 0, word_index: 0, is_exact: true, .. })); // new + // assert_matches!(matches.next(), Some(TmpMatch { query_index: 1, word_index: 1, is_exact: false, .. })); // york + // assert_matches!(matches.next(), Some(TmpMatch { query_index: 1, word_index: 1, is_exact: true, .. })); // york + // assert_matches!(matches.next(), Some(TmpMatch { query_index: 2, word_index: 2, is_exact: false, .. })); // city + // assert_matches!(matches.next(), Some(TmpMatch { query_index: 2, word_index: 2, is_exact: true, .. })); // city + // assert_matches!(matches.next(), Some(TmpMatch { query_index: 4, word_index: 3, is_exact: true, .. })); // subway + // assert_matches!(matches.next(), None); + // }); + // assert_matches!(iter.next(), None); + // } + + // #[test] + // fn cumulative_word_indices() { + // let mut store = InMemorySetStore::from_iter(vec![ + // ("NYC", &[doc_index(0, 0)][..]), + // ("long", &[doc_index(0, 1)][..]), + // ("subway", &[doc_index(0, 2)][..]), + // ("cool", &[doc_index(0, 3)][..]), + // ]); + + // store.add_synonym("new york city", SetBuf::from_dirty(vec!["NYC"])); + // store.add_synonym("subway", SetBuf::from_dirty(vec!["underground train"])); + + // let builder = QueryBuilder::new(&store); + // let results = builder.query("new york city long subway cool ", 0..20).unwrap(); + // let mut iter = results.into_iter(); + + // assert_matches!(iter.next(), Some(Document { id: DocumentId(0), matches, .. }) => { + // let mut matches = matches.into_iter(); + // assert_matches!(matches.next(), Some(TmpMatch { query_index: 0, word_index: 0, is_exact: true, .. })); // new = NYC + // assert_matches!(matches.next(), Some(TmpMatch { query_index: 1, word_index: 1, is_exact: true, .. })); // york = NYC + // assert_matches!(matches.next(), Some(TmpMatch { query_index: 2, word_index: 2, is_exact: true, .. })); // city = NYC + // assert_matches!(matches.next(), Some(TmpMatch { query_index: 3, word_index: 3, is_exact: true, .. })); // long + // assert_matches!(matches.next(), Some(TmpMatch { query_index: 4, word_index: 4, is_exact: true, .. })); // subway = underground + // assert_matches!(matches.next(), Some(TmpMatch { query_index: 5, word_index: 5, is_exact: true, .. })); // subway = train + // assert_matches!(matches.next(), Some(TmpMatch { query_index: 6, word_index: 6, is_exact: true, .. })); // cool + // assert_matches!(matches.next(), None); + // }); + // assert_matches!(iter.next(), None); + // } + + // #[test] + // fn deunicoded_synonyms() { + // let mut store = InMemorySetStore::from_iter(vec![ + // ("telephone", &[doc_index(0, 0)][..]), // meilidb-data indexes the unidecoded + // ("téléphone", &[doc_index(0, 0)][..]), // and the original words with the same DocIndex + + // ("iphone", &[doc_index(1, 0)][..]), + // ]); + + // store.add_synonym("téléphone", SetBuf::from_dirty(vec!["iphone"])); + + // let builder = QueryBuilder::new(&store); + // let results = builder.query("telephone", 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(TmpMatch { query_index: 0, .. })); + // assert_matches!(iter.next(), Some(TmpMatch { query_index: 0, .. })); + // assert_matches!(iter.next(), None); + // }); + // assert_matches!(iter.next(), Some(Document { id: DocumentId(1), matches, .. }) => { + // let mut iter = matches.into_iter(); + // assert_matches!(iter.next(), Some(TmpMatch { query_index: 0, .. })); + // assert_matches!(iter.next(), None); + // }); + // assert_matches!(iter.next(), None); + + // let builder = QueryBuilder::new(&store); + // let results = builder.query("téléphone", 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(TmpMatch { query_index: 0, .. })); + // assert_matches!(iter.next(), Some(TmpMatch { query_index: 0, .. })); + // assert_matches!(iter.next(), None); + // }); + // assert_matches!(iter.next(), Some(Document { id: DocumentId(1), matches, .. }) => { + // let mut iter = matches.into_iter(); + // assert_matches!(iter.next(), Some(TmpMatch { query_index: 0, .. })); + // assert_matches!(iter.next(), None); + // }); + // assert_matches!(iter.next(), None); + + // let builder = QueryBuilder::new(&store); + // let results = builder.query("télephone", 0..20).unwrap(); + // let mut iter = results.into_iter(); + + // assert_matches!(iter.next(), Some(Document { id: DocumentId(1), matches, .. }) => { + // let mut iter = matches.into_iter(); + // assert_matches!(iter.next(), Some(TmpMatch { query_index: 0, .. })); + // assert_matches!(iter.next(), None); + // }); + // assert_matches!(iter.next(), Some(Document { id: DocumentId(0), matches, .. }) => { + // let mut iter = matches.into_iter(); + // assert_matches!(iter.next(), Some(TmpMatch { query_index: 0, distance: 1, word_index: 0, is_exact: false, .. })); // iphone + // assert_matches!(iter.next(), Some(TmpMatch { query_index: 0, distance: 1, word_index: 0, is_exact: false, .. })); // téléphone + // assert_matches!(iter.next(), None); + // }); + // assert_matches!(iter.next(), None); + // } + + // #[test] + // fn simple_concatenation() { + // let store = InMemorySetStore::from_iter(vec![ + // ("iphone", &[doc_index(0, 0)][..]), + // ("case", &[doc_index(0, 1)][..]), + // ]); + + // let builder = QueryBuilder::new(&store); + // let results = builder.query("i phone case", 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(TmpMatch { query_index: 0, word_index: 0, distance: 0, .. })); // iphone + // assert_matches!(iter.next(), Some(TmpMatch { query_index: 1, word_index: 1, distance: 0, .. })); // iphone + // assert_matches!(iter.next(), Some(TmpMatch { query_index: 1, word_index: 0, distance: 1, .. })); // phone + // assert_matches!(iter.next(), Some(TmpMatch { query_index: 2, word_index: 2, distance: 0, .. })); // case + // assert_matches!(iter.next(), None); + // }); + // assert_matches!(iter.next(), None); + // } +}