perf(#12): push suggest() filtering + LIMIT to SQL
Replace the in-memory approach (list_files → filter in Rust) with SQL-level ILIKE + relevance ORDER BY + LIMIT. - Add suggest_files_by_name() to FileReadPort (default impl for stubs) - Add suggest_folders_by_name() to FolderRepository (default impl) - Implement efficient SQL in FileBlobReadRepository & FolderDbRepository with LOWER(name) LIKE pattern, 3-tier relevance sorting, and LIMIT - Rewrite SearchService::suggest() to call new methods in parallel Before: 50K files → ~10 MB transferred, 52K string comparisons After: 50K files → ~20 rows transferred, index-assisted scan
This commit is contained in:
@@ -120,4 +120,27 @@ pub trait FolderRepository: Send + Sync + 'static {
|
||||
let _ = (folder_id, name_contains, user_id);
|
||||
Ok(Vec::new())
|
||||
}
|
||||
|
||||
/// Return up to `limit` folders whose name contains `query` (case-insensitive).
|
||||
///
|
||||
/// Results are ordered by relevance (exact > starts-with > contains) for
|
||||
/// autocomplete suggestions.
|
||||
///
|
||||
/// The default implementation falls back to `list_folders` + in-memory
|
||||
/// filter so that stubs and mocks compile without changes.
|
||||
async fn suggest_folders_by_name(
|
||||
&self,
|
||||
parent_id: Option<&str>,
|
||||
query: &str,
|
||||
limit: usize,
|
||||
) -> Result<Vec<Folder>, DomainError> {
|
||||
let all = self.list_folders(parent_id).await?;
|
||||
let q = query.to_lowercase();
|
||||
let mut matched: Vec<Folder> = all
|
||||
.into_iter()
|
||||
.filter(|f| f.name().to_lowercase().contains(&q))
|
||||
.collect();
|
||||
matched.truncate(limit);
|
||||
Ok(matched)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user