fix(search): also support exact phrase matching such as ='test phrase'

This commit is contained in:
perf3ct 2025-10-21 10:12:14 -07:00
parent 4fa4112840
commit fb0d971e48
No known key found for this signature in database
GPG Key ID: 569C4EEC436F5232
2 changed files with 15 additions and 7 deletions

View File

@ -118,7 +118,7 @@ class NoteContentFulltextExp extends Expression {
}
/**
* Checks if content contains the exact word (with word boundaries)
* Checks if content contains the exact word (with word boundaries) or exact phrase
* This is case-insensitive since content and token are already normalized
*/
private containsExactWord(token: string, content: string): boolean {
@ -126,7 +126,13 @@ class NoteContentFulltextExp extends Expression {
const normalizedToken = normalizeSearchText(token);
const normalizedContent = normalizeSearchText(content);
// Split content into words and check for exact match
// If token contains spaces, it's a multi-word phrase from quotes
// Check for substring match (consecutive phrase)
if (normalizedToken.includes(' ')) {
return normalizedContent.includes(normalizedToken);
}
// For single words, split content into words and check for exact match
const words = normalizedContent.split(/\s+/);
return words.some(word => word === normalizedToken);
}

View File

@ -15,18 +15,19 @@ type Comparator<T> = (comparedValue: T) => (val: string) => boolean;
const stringComparators: Record<string, Comparator<string>> = {
"=": (comparedValue) => (val) => {
// For the = operator, check if the value contains the exact word or phrase
// This is case-insensitive since both values are already lowercased
// This is case-insensitive
if (!val) return false;
const normalizedVal = normalizeSearchText(val);
const normalizedCompared = normalizeSearchText(comparedValue);
// If comparedValue has multiple words, check for exact phrase
// If comparedValue has spaces, it's a multi-word phrase
// Check for substring match (consecutive phrase)
if (normalizedCompared.includes(" ")) {
return normalizedVal.includes(normalizedCompared);
}
// For single word, split into words and check for exact match
// For single word, split into words and check for exact word match
const words = normalizedVal.split(/\s+/);
return words.some(word => word === normalizedCompared);
},
@ -37,12 +38,13 @@ const stringComparators: Record<string, Comparator<string>> = {
const normalizedVal = normalizeSearchText(val);
const normalizedCompared = normalizeSearchText(comparedValue);
// If comparedValue has multiple words, check for exact phrase
// If comparedValue has spaces, it's a multi-word phrase
// Check for substring match (consecutive phrase) and negate
if (normalizedCompared.includes(" ")) {
return !normalizedVal.includes(normalizedCompared);
}
// For single word, split into words and check for exact match
// For single word, split into words and check for exact word match, then negate
const words = normalizedVal.split(/\s+/);
return !words.some(word => word === normalizedCompared);
},