feat: Make typo factor configurable
Fixes https://github.com/valeriansaliou/sonic/issues/394.
This commit is contained in:
1 parent
0f79d0dab8
commit
9bdd4a2024
11 files changed
+120
-13
No files matched your search
@@ -120,6 +120,11 @@ pub struct SearchConfig {
|
||||
pub list_limit_default: u16,
|
||||
|
||||
pub list_limit_maximum: u16,
|
||||
|
||||
/// Word lengths from which one more typo is allowed when correcting words
|
||||
/// (e.g. `[4, 7, 10]` allows 1 typo from 4 letters, 2 typos from 7 letters
|
||||
/// and 3 typos from 10 letters). Empty means no typo correction.
|
||||
pub typo_factor_word_lengths: Vec<usize>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize)]
|
||||
@@ -386,6 +391,7 @@ pub(crate) mod tests {
|
||||
suggest_limit_maximum = 20
|
||||
list_limit_default = 100
|
||||
list_limit_maximum = 500
|
||||
typo_factor_word_lengths = [4, 7, 10]
|
||||
|
||||
[store.kv]
|
||||
path = "./data/store/kv/"
|
||||
|
||||
@@ -209,7 +209,10 @@ impl super::Executor {
|
||||
continue 'terms;
|
||||
}
|
||||
|
||||
let max_typo_factor = typo_factor(original_word_len);
|
||||
let max_typo_factor = typo_factor(
|
||||
original_word_len,
|
||||
&self.app_conf.search.typo_factor_word_lengths,
|
||||
);
|
||||
let mut typo_factor = 1u32;
|
||||
|
||||
// TODO: Rework the Levenshtein query feature to avoid repeating
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
use super::types::QuerySearchLimit;
|
||||
use crate::lexer::preprocessor::PreprocessorOutput;
|
||||
use crate::store::StoreItemPart;
|
||||
use crate::store::fst::typo_factor;
|
||||
|
||||
impl super::Executor {
|
||||
pub fn suggest(
|
||||
@@ -27,10 +28,12 @@ impl super::Executor {
|
||||
if let (Some(token), None) = (tokens.next(), tokens.next()) {
|
||||
let len = token.as_original().len();
|
||||
let term = token.into_normalized();
|
||||
let max_typo_factor =
|
||||
typo_factor(len, &self.app_conf.search.typo_factor_word_lengths);
|
||||
|
||||
tracing::debug!("running suggest on word: {term:?}");
|
||||
|
||||
return match fst_store.suggest_words(term, len, limit as usize, None) {
|
||||
return match fst_store.suggest_words(term, len, limit as usize, max_typo_factor) {
|
||||
Some(words) => Ok(Some(words.map(|(k, _)| k))),
|
||||
None => Ok(None),
|
||||
};
|
||||
|
||||
@@ -245,7 +245,7 @@ impl FstStore {
|
||||
// on user input.
|
||||
original_word_len: usize,
|
||||
limit: usize,
|
||||
max_typo_factor: Option<u32>,
|
||||
max_typo_factor: u32,
|
||||
) -> Option<impl ExactSizeIterator<Item = (String, u16)> + DoubleEndedIterator + use<>> {
|
||||
use indexmap::IndexMap;
|
||||
|
||||
@@ -276,8 +276,6 @@ impl FstStore {
|
||||
|
||||
// Try to fuzzy-suggest other words? (e.g. correct typos)
|
||||
if self.action_config.fuzzy_matching_enabled && found_words.len() < limit {
|
||||
// Allow more typos in word as the word gets longer, up to a maximum limit
|
||||
let max_typo_factor = max_typo_factor.unwrap_or(typo_factor(original_word_len));
|
||||
let mut typo_factor = 1u32;
|
||||
|
||||
// TODO: Rework the Levenshtein query feature to avoid repeating
|
||||
@@ -403,13 +401,14 @@ impl FstStore {
|
||||
}
|
||||
|
||||
/// Allow more typos in word as the word gets longer, up to a maximum limit.
|
||||
pub(crate) fn typo_factor(word_len: usize) -> u32 {
|
||||
match word_len {
|
||||
1..=3 => 0,
|
||||
4..=6 => 1,
|
||||
7..=9 => 2,
|
||||
_ => 3,
|
||||
}
|
||||
///
|
||||
/// `typo_factor_word_lengths` lists the word lengths from which one more typo
|
||||
/// is allowed (see `search.typo_factor_word_lengths`).
|
||||
pub(crate) fn typo_factor(word_len: usize, typo_factor_word_lengths: &[usize]) -> u32 {
|
||||
typo_factor_word_lengths
|
||||
.iter()
|
||||
.filter(|&&min_word_len| word_len >= min_word_len)
|
||||
.count() as u32
|
||||
}
|
||||
|
||||
// MARK: - Helpers
|
||||
|
||||
Reference in new issue
Block a user