mirror of
https://github.com/meilisearch/MeiliSearch
synced 2024-12-24 13:40:31 +01:00
Merge #732
732: Interpret synonyms as phrases r=loiclec a=loiclec # Pull Request ## Related issue Fixes (when merged into meilisearch) https://github.com/meilisearch/meilisearch/issues/3125 ## What does this PR do? We now map multi-word synonyms to phrases instead of loose words. Such that the request: ``` btw I am going to nyc soon ``` is interpreted as (when the synonym interpretation is chosen for both `btw` and `nyc`): ``` "by the way" I am going to "New York City" soon ``` instead of: ``` by the way I am going to New York City soon ``` This prevents queries containing multi-word synonyms to exceed to word length limit and degrade the search performance. In terms of relevancy, there is a debate to have. I personally think this could be considered an improvement, since it would be strange for a user to search for: ``` good DIY project ``` and have a result such as: ``` { "text": "whether it is a good project to do, you'll have to decide for yourself" } ``` However, for synonyms such as `NYC -> New York City`, then we will stop matching documents where `New York` is separated from `City`. This is however solvable by adding an additional mapping: `NYC -> New York`. ## Performance With the old behaviour, some long search requests making heavy uses of synonyms could take minutes to be executed. This is no longer the case, these search requests now take an average amount of time to be resolved. Co-authored-by: Loïc Lecrenier <loic.lecrenier@me.com>
This commit is contained in:
commit
49f58b2c47
@ -339,18 +339,18 @@ fn typos(word: String, authorize_typos: bool, config: TypoConfig) -> QueryKind {
|
||||
/// and create the list of operations for the query tree
|
||||
fn synonyms(ctx: &impl Context, word: &[&str]) -> heed::Result<Option<Vec<Operation>>> {
|
||||
let synonyms = ctx.synonyms(word)?;
|
||||
|
||||
Ok(synonyms.map(|synonyms| {
|
||||
synonyms
|
||||
.into_iter()
|
||||
.map(|synonym| {
|
||||
let words = synonym
|
||||
.into_iter()
|
||||
.map(|word| {
|
||||
Operation::Query(Query { prefix: false, kind: QueryKind::exact(word) })
|
||||
if synonym.len() == 1 {
|
||||
Operation::Query(Query {
|
||||
prefix: false,
|
||||
kind: QueryKind::exact(synonym[0].clone()),
|
||||
})
|
||||
.collect();
|
||||
Operation::and(words)
|
||||
} else {
|
||||
Operation::Phrase(synonym.into_iter().map(Some).collect())
|
||||
}
|
||||
})
|
||||
.collect()
|
||||
}))
|
||||
@ -1058,9 +1058,7 @@ mod test {
|
||||
AND
|
||||
OR
|
||||
Exact { word: "hi" }
|
||||
AND
|
||||
Exact { word: "good" }
|
||||
Exact { word: "morning" }
|
||||
PHRASE [Some("good"), Some("morning")]
|
||||
Tolerant { word: "hello", max typo: 1 }
|
||||
OR
|
||||
Exact { word: "earth" }
|
||||
@ -1070,6 +1068,24 @@ mod test {
|
||||
"###);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn simple_synonyms() {
|
||||
let query = "nyc";
|
||||
let tokens = query.tokenize();
|
||||
|
||||
let (query_tree, _) = TestContext::default()
|
||||
.build(TermsMatchingStrategy::Last, true, None, tokens)
|
||||
.unwrap()
|
||||
.unwrap();
|
||||
|
||||
insta::assert_debug_snapshot!(query_tree, @r###"
|
||||
OR
|
||||
PHRASE [Some("new"), Some("york")]
|
||||
PHRASE [Some("new"), Some("york"), Some("city")]
|
||||
PrefixExact { word: "nyc" }
|
||||
"###);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn complex_synonyms() {
|
||||
let query = "new york city ";
|
||||
@ -1092,16 +1108,11 @@ mod test {
|
||||
AND
|
||||
OR
|
||||
Exact { word: "nyc" }
|
||||
AND
|
||||
Exact { word: "new" }
|
||||
Exact { word: "york" }
|
||||
Exact { word: "city" }
|
||||
PHRASE [Some("new"), Some("york"), Some("city")]
|
||||
Tolerant { word: "newyork", max typo: 1 }
|
||||
Exact { word: "city" }
|
||||
Exact { word: "nyc" }
|
||||
AND
|
||||
Exact { word: "new" }
|
||||
Exact { word: "york" }
|
||||
PHRASE [Some("new"), Some("york")]
|
||||
Tolerant { word: "newyorkcity", max typo: 1 }
|
||||
"###);
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user