From 55b210d7c5a0a03567ae1039501c3c756036ef86 Mon Sep 17 00:00:00 2001 From: zadam Date: Wed, 27 May 2020 00:09:19 +0200 Subject: [PATCH] added not() expression --- spec/lexer.spec.js | 5 +++++ spec/parser.spec.js | 2 +- spec/search.spec.js | 16 ++++++++++++++++ src/services/search/parser.js | 10 ++++++++++ 4 files changed, 32 insertions(+), 1 deletion(-) diff --git a/spec/lexer.spec.js b/spec/lexer.spec.js index 4c65cecf3..2d366e763 100644 --- a/spec/lexer.spec.js +++ b/spec/lexer.spec.js @@ -63,4 +63,9 @@ describe("Lexer expression", () => { expect(lexer(`# ~author.title = 'Hugh Howey' AND note.'book title' = 'Silo'`).expressionTokens) .toEqual(["#", "~author", ".", "title", "=", "hugh howey", "and", "note", ".", "book title", "=", "silo"]); }); + + it("negation of sub-expression", () => { + expect(lexer(`# not(#capital) and note.noteId != "root"`).expressionTokens) + .toEqual(["#", "not", "(", "#capital", ")", "and", "note", ".", "noteid", "!=", "root"]); + }); }); diff --git a/spec/parser.spec.js b/spec/parser.spec.js index 360e679fa..b5ac8d8ee 100644 --- a/spec/parser.spec.js +++ b/spec/parser.spec.js @@ -46,7 +46,7 @@ describe("Parser", () => { it("simple label AND", () => { const rootExp = parser({ fulltextTokens: [], - expressionTokens: ["#first", "=", "text", "AND", "#second", "=", "text"], + expressionTokens: ["#first", "=", "text", "and", "#second", "=", "text"], parsingContext: new ParsingContext(true) }); diff --git a/spec/search.spec.js b/spec/search.spec.js index f193857bc..35ec670d8 100644 --- a/spec/search.spec.js +++ b/spec/search.spec.js @@ -512,5 +512,21 @@ describe("Search", () => { expect(searchResults.length).toEqual(4); }); + it("test not(...)", async () => { + const italy = note("Italy").label("capital", "Rome"); + const slovakia = note("Slovakia").label("capital", "Bratislava"); + + rootNote + .child(note("Europe") + .child(slovakia) + .child(italy)); + + const parsingContext = new ParsingContext(); + + let searchResults = await searchService.findNotesWithQuery('# not(#capital) and note.noteId != root', parsingContext); + expect(searchResults.length).toEqual(1); + expect(noteCache.notes[searchResults[0].noteId].title).toEqual("Europe"); + }); + // FIXME: test what happens when we order without any filter criteria }); diff --git a/src/services/search/parser.js b/src/services/search/parser.js index e7b6bac15..64102b6b5 100644 --- a/src/services/search/parser.js +++ b/src/services/search/parser.js @@ -255,6 +255,16 @@ function getExpression(tokens, parsingContext, level = 0) { return exp; } + else if (token === 'not') { + i += 1; + + if (!Array.isArray(tokens[i])) { + parsingContext.addError(`not keyword should be followed by sub-expression in parenthesis, got ${tokens[i]} instead`); + continue; + } + + expressions.push(new NotExp(getExpression(tokens[i], parsingContext, level++))); + } else if (token === 'note') { i++;