diff --git a/src/services/search/expressions/note_content_protected_fulltext.js b/src/services/search/expressions/note_content_protected_fulltext.js index c93017a9a..05130e087 100644 --- a/src/services/search/expressions/note_content_protected_fulltext.js +++ b/src/services/search/expressions/note_content_protected_fulltext.js @@ -10,7 +10,7 @@ const utils = require("../../utils"); // FIXME: create common subclass with NoteContentUnprotectedFulltextExp to avoid duplication class NoteContentProtectedFulltextExp extends Expression { - constructor(operator, tokens, raw) { + constructor(operator, {tokens, raw, flatText}) { super(); if (operator !== '*=*') { @@ -19,6 +19,7 @@ class NoteContentProtectedFulltextExp extends Expression { this.tokens = tokens; this.raw = !!raw; + this.flatText = !!flatText; } execute(inputNoteSet) { @@ -49,7 +50,17 @@ class NoteContentProtectedFulltextExp extends Expression { content = this.preprocessContent(content, type, mime); - if (!this.tokens.find(token => !content.includes(token))) { + const nonMatchingToken = this.tokens.find(token => + !content.includes(token) && + ( + // in case of default fulltext search we should consider both title, attrs and content + // so e.g. "hello world" should match when "hello" is in title and "world" in content + !this.flatText + || !becca.notes[noteId].getFlatText().includes(token) + ) + ); + + if (!nonMatchingToken) { resultNoteSet.add(becca.notes[noteId]); } } diff --git a/src/services/search/expressions/note_content_unprotected_fulltext.js b/src/services/search/expressions/note_content_unprotected_fulltext.js index 7b97722b8..7abbd0d78 100644 --- a/src/services/search/expressions/note_content_unprotected_fulltext.js +++ b/src/services/search/expressions/note_content_unprotected_fulltext.js @@ -8,7 +8,7 @@ const utils = require("../../utils"); // FIXME: create common subclass with NoteContentProtectedFulltextExp to avoid duplication class NoteContentUnprotectedFulltextExp extends Expression { - constructor(operator, tokens, raw) { + constructor(operator, {tokens, raw, flatText}) { super(); if (operator !== '*=*') { @@ -17,6 +17,7 @@ class NoteContentUnprotectedFulltextExp extends Expression { this.tokens = tokens; this.raw = !!raw; + this.flatText = !!flatText; } execute(inputNoteSet) { @@ -35,7 +36,17 @@ class NoteContentUnprotectedFulltextExp extends Expression { content = this.preprocessContent(content, type, mime); - if (!this.tokens.find(token => !content.includes(token))) { + const nonMatchingToken = this.tokens.find(token => + !content.includes(token) && + ( + // in case of default fulltext search we should consider both title, attrs and content + // so e.g. "hello world" should match when "hello" is in title and "world" in content + !this.flatText + || !becca.notes[noteId].getFlatText().includes(token) + ) + ); + + if (!nonMatchingToken) { resultNoteSet.add(becca.notes[noteId]); } } diff --git a/src/services/search/services/parse.js b/src/services/search/services/parse.js index 02d2cc3bb..9ba5ce506 100644 --- a/src/services/search/services/parse.js +++ b/src/services/search/services/parse.js @@ -32,8 +32,8 @@ function getFulltext(tokens, searchContext) { if (!searchContext.fastSearch) { return new OrExp([ new NoteFlatTextExp(tokens), - new NoteContentProtectedFulltextExp('*=*', tokens), - new NoteContentUnprotectedFulltextExp('*=*', tokens) + new NoteContentProtectedFulltextExp('*=*', {tokens, flatText: true}), + new NoteContentUnprotectedFulltextExp('*=*', {tokens, flatText: true}) ]); } else { @@ -141,8 +141,8 @@ function getExpression(tokens, searchContext, level = 0) { i++; return new OrExp([ - new NoteContentUnprotectedFulltextExp(operator, [tokens[i].token], raw), - new NoteContentProtectedFulltextExp(operator, [tokens[i].token], raw) + new NoteContentUnprotectedFulltextExp(operator, {tokens: [tokens[i].token], raw }), + new NoteContentProtectedFulltextExp(operator, {tokens: [tokens[i].token], raw }) ]); } @@ -196,8 +196,8 @@ function getExpression(tokens, searchContext, level = 0) { return new OrExp([ new PropertyComparisonExp(searchContext, 'title', '*=*', tokens[i].token), - new NoteContentProtectedFulltextExp('*=*', [tokens[i].token]), - new NoteContentUnprotectedFulltextExp('*=*', [tokens[i].token]) + new NoteContentProtectedFulltextExp('*=*', {tokens: [tokens[i].token]}), + new NoteContentUnprotectedFulltextExp('*=*', {tokens: [tokens[i].token]}) ]); }