From 45edef2d715c7d5c6dc384fe1f58e836480fbeeb Mon Sep 17 00:00:00 2001 From: zadam Date: Wed, 11 May 2022 23:06:14 +0200 Subject: [PATCH] new ~ operator in search for regex --- .../search/expressions/note_content_fulltext.js | 15 +++++++++++++-- src/services/search/services/build_comparator.js | 11 +++++++++++ src/services/search/services/parse.js | 2 +- 3 files changed, 25 insertions(+), 3 deletions(-) diff --git a/src/services/search/expressions/note_content_fulltext.js b/src/services/search/expressions/note_content_fulltext.js index bab10644e..f7758ef31 100644 --- a/src/services/search/expressions/note_content_fulltext.js +++ b/src/services/search/expressions/note_content_fulltext.js @@ -8,7 +8,17 @@ const protectedSessionService = require('../../protected_session'); const striptags = require('striptags'); const utils = require("../../utils"); -const ALLOWED_OPERATORS = ['*=*', '=', '*=', '=*']; +const ALLOWED_OPERATORS = ['*=*', '=', '*=', '=*', '~']; + +const cachedRegexes = {}; + +function getRegex(str) { + if (!(str in cachedRegexes)) { + cachedRegexes[str] = new RegExp(str, 'ms'); // multiline, dot-all + } + + return cachedRegexes[str]; +} class NoteContentFulltextExp extends Expression { constructor(operator, {tokens, raw, flatText}) { @@ -57,7 +67,8 @@ class NoteContentFulltextExp extends Expression { if ((this.operator === '=' && token === content) || (this.operator === '*=' && content.endsWith(token)) - || (this.operator === '=*' && content.startsWith(token))) { + || (this.operator === '=*' && content.startsWith(token)) + || (this.operator === '~' && getRegex(token).test(content))) { resultNoteSet.add(becca.notes[noteId]); } diff --git a/src/services/search/services/build_comparator.js b/src/services/search/services/build_comparator.js index 561f3df66..0776b834f 100644 --- a/src/services/search/services/build_comparator.js +++ b/src/services/search/services/build_comparator.js @@ -1,3 +1,13 @@ +const cachedRegexes = {}; + +function getRegex(str) { + if (!(str in cachedRegexes)) { + cachedRegexes[str] = new RegExp(str); + } + + return cachedRegexes[str]; +} + const stringComparators = { "=": comparedValue => (val => val === comparedValue), "!=": comparedValue => (val => val !== comparedValue), @@ -8,6 +18,7 @@ const stringComparators = { "*=": comparedValue => (val => val && val.endsWith(comparedValue)), "=*": comparedValue => (val => val && val.startsWith(comparedValue)), "*=*": comparedValue => (val => val && val.includes(comparedValue)), + "~": comparedValue => (val => val && !!getRegex(comparedValue).test(val)), }; const numericComparators = { diff --git a/src/services/search/services/parse.js b/src/services/search/services/parse.js index 2295ded88..32ce9eeec 100644 --- a/src/services/search/services/parse.js +++ b/src/services/search/services/parse.js @@ -40,7 +40,7 @@ function getFulltext(tokens, searchContext) { } function isOperator(str) { - return str.match(/^[!=<>*]+$/); + return str.match(/^[!=<>*~]+$/); } function getExpression(tokens, searchContext, level = 0) {