From 5718631889ecb8fa01e72d2c2f374ebdc0de44a7 Mon Sep 17 00:00:00 2001 From: perfectra1n Date: Wed, 18 Mar 2026 09:46:24 -0700 Subject: [PATCH] fix(search): resolve issue with autocomplete with search performance enhancements --- .../src/services/search/expressions/note_flat_text.ts | 4 ++-- apps/server/src/services/search/search_context.ts | 3 +++ apps/server/src/services/search/services/search.ts | 10 +++++----- apps/server/src/services/search/services/types.ts | 2 ++ 4 files changed, 12 insertions(+), 7 deletions(-) diff --git a/apps/server/src/services/search/expressions/note_flat_text.ts b/apps/server/src/services/search/expressions/note_flat_text.ts index b1ceac991e..ef3efbf66f 100644 --- a/apps/server/src/services/search/expressions/note_flat_text.ts +++ b/apps/server/src/services/search/expressions/note_flat_text.ts @@ -96,10 +96,10 @@ class NoteFlatTextExp extends Expression { const candidateNotes = this.getCandidateNotes(inputNoteSet, searchContext); - // Fast path for single-token searches with a limit (e.g. autocomplete): + // Fast path for single-token autocomplete searches: // Skip the expensive recursive parent walk and just use getBestNotePath(). // The flat text already matched, so we know the token is present. - if (this.tokens.length === 1 && searchContext.limit) { + if (this.tokens.length === 1 && searchContext.autocomplete) { for (const note of candidateNotes) { if (!resultNoteSet.hasNoteId(note.noteId)) { const notePath = note.getBestNotePath(); diff --git a/apps/server/src/services/search/search_context.ts b/apps/server/src/services/search/search_context.ts index 314c7e7ce6..55d4df5d2f 100644 --- a/apps/server/src/services/search/search_context.ts +++ b/apps/server/src/services/search/search_context.ts @@ -18,6 +18,8 @@ class SearchContext { debug?: boolean; debugInfo: {} | null; fuzzyAttributeSearch: boolean; + /** When true, skip the two-phase fuzzy fallback and use the single-token fast path. */ + autocomplete: boolean; enableFuzzyMatching: boolean; // Controls whether fuzzy matching is enabled for this search phase highlightedTokens: string[]; originalQuery: string; @@ -46,6 +48,7 @@ class SearchContext { this.debug = params.debug; this.debugInfo = null; this.fuzzyAttributeSearch = !!params.fuzzyAttributeSearch; + this.autocomplete = !!params.autocomplete; this.enableFuzzyMatching = true; // Default to true for backward compatibility this.highlightedTokens = []; this.originalQuery = ""; diff --git a/apps/server/src/services/search/services/search.ts b/apps/server/src/services/search/services/search.ts index 7ee3e494f4..b533c185fe 100644 --- a/apps/server/src/services/search/services/search.ts +++ b/apps/server/src/services/search/services/search.ts @@ -248,10 +248,10 @@ function findResultsWithExpression(expression: Expression, searchContext: Search return performSearch(expression, searchContext, false); } - // For limited searches (e.g. autocomplete), skip the expensive two-phase - // fuzzy fallback. The user is typing and will refine their query — exact - // matching is sufficient and avoids a second full scan of all notes. - if (searchContext.limit) { + // For autocomplete searches, skip the expensive two-phase fuzzy fallback. + // The user is typing and will refine their query — exact matching is + // sufficient and avoids a second full scan of all notes. + if (searchContext.autocomplete) { return performSearch(expression, searchContext, false); } @@ -645,7 +645,7 @@ function searchNotesForAutocomplete(query: string, fastSearch: boolean = true) { fuzzyAttributeSearch: true, ignoreInternalAttributes: true, ancestorNoteId: hoistedNoteService.isHoistedInHiddenSubtree() ? "root" : hoistedNoteService.getHoistedNoteId(), - limit: 200 + autocomplete: true }); const allSearchResults = findResultsWithQuery(query, searchContext); diff --git a/apps/server/src/services/search/services/types.ts b/apps/server/src/services/search/services/types.ts index 7edc3b4ae5..60d00540c6 100644 --- a/apps/server/src/services/search/services/types.ts +++ b/apps/server/src/services/search/services/types.ts @@ -21,4 +21,6 @@ export interface SearchParams { limit?: number | null; debug?: boolean; fuzzyAttributeSearch?: boolean; + /** When true, skip the two-phase fuzzy fallback and use the single-token fast path. */ + autocomplete?: boolean; }