renamed ParsingContext to SearchContext

This commit is contained in:
zadam 2020-09-08 21:47:37 +02:00
parent 0c5f842626
commit a73733d0fc
7 changed files with 151 additions and 151 deletions

View File

@ -1,4 +1,4 @@
const ParsingContext = require("../../src/services/search/parsing_context.js"); const SearchContext = require("../../src/services/search/search_context.js");
const parse = require('../../src/services/search/services/parse.js'); const parse = require('../../src/services/search/services/parse.js');
function tokens(toks, cur = 0) { function tokens(toks, cur = 0) {
@ -24,7 +24,7 @@ describe("Parser", () => {
const rootExp = parse({ const rootExp = parse({
fulltextTokens: tokens(["hello", "hi"]), fulltextTokens: tokens(["hello", "hi"]),
expressionTokens: [], expressionTokens: [],
parsingContext: new ParsingContext({includeNoteContent: false}) searchContext: new SearchContext({includeNoteContent: false})
}); });
expect(rootExp.constructor.name).toEqual("AndExp"); expect(rootExp.constructor.name).toEqual("AndExp");
@ -36,7 +36,7 @@ describe("Parser", () => {
const rootExp = parse({ const rootExp = parse({
fulltextTokens: tokens(["hello", "hi"]), fulltextTokens: tokens(["hello", "hi"]),
expressionTokens: [], expressionTokens: [],
parsingContext: new ParsingContext({includeNoteContent: true}) searchContext: new SearchContext({includeNoteContent: true})
}); });
expect(rootExp.constructor.name).toEqual("AndExp"); expect(rootExp.constructor.name).toEqual("AndExp");
@ -59,7 +59,7 @@ describe("Parser", () => {
const rootExp = parse({ const rootExp = parse({
fulltextTokens: [], fulltextTokens: [],
expressionTokens: tokens(["#mylabel", "=", "text"]), expressionTokens: tokens(["#mylabel", "=", "text"]),
parsingContext: new ParsingContext() searchContext: new SearchContext()
}); });
expect(rootExp.constructor.name).toEqual("LabelComparisonExp"); expect(rootExp.constructor.name).toEqual("LabelComparisonExp");
@ -72,7 +72,7 @@ describe("Parser", () => {
let rootExp = parse({ let rootExp = parse({
fulltextTokens: [], fulltextTokens: [],
expressionTokens: tokens(["#!mylabel"]), expressionTokens: tokens(["#!mylabel"]),
parsingContext: new ParsingContext() searchContext: new SearchContext()
}); });
expect(rootExp.constructor.name).toEqual("NotExp"); expect(rootExp.constructor.name).toEqual("NotExp");
@ -83,7 +83,7 @@ describe("Parser", () => {
rootExp = parse({ rootExp = parse({
fulltextTokens: [], fulltextTokens: [],
expressionTokens: tokens(["~!myrelation"]), expressionTokens: tokens(["~!myrelation"]),
parsingContext: new ParsingContext() searchContext: new SearchContext()
}); });
expect(rootExp.constructor.name).toEqual("NotExp"); expect(rootExp.constructor.name).toEqual("NotExp");
@ -96,7 +96,7 @@ describe("Parser", () => {
const rootExp = parse({ const rootExp = parse({
fulltextTokens: [], fulltextTokens: [],
expressionTokens: tokens(["#first", "=", "text", "and", "#second", "=", "text"]), expressionTokens: tokens(["#first", "=", "text", "and", "#second", "=", "text"]),
parsingContext: new ParsingContext(true) searchContext: new SearchContext(true)
}); });
expect(rootExp.constructor.name).toEqual("AndExp"); expect(rootExp.constructor.name).toEqual("AndExp");
@ -113,7 +113,7 @@ describe("Parser", () => {
const rootExp = parse({ const rootExp = parse({
fulltextTokens: [], fulltextTokens: [],
expressionTokens: tokens(["#first", "=", "text", "#second", "=", "text"]), expressionTokens: tokens(["#first", "=", "text", "#second", "=", "text"]),
parsingContext: new ParsingContext() searchContext: new SearchContext()
}); });
expect(rootExp.constructor.name).toEqual("AndExp"); expect(rootExp.constructor.name).toEqual("AndExp");
@ -130,7 +130,7 @@ describe("Parser", () => {
const rootExp = parse({ const rootExp = parse({
fulltextTokens: [], fulltextTokens: [],
expressionTokens: tokens(["#first", "=", "text", "or", "#second", "=", "text"]), expressionTokens: tokens(["#first", "=", "text", "or", "#second", "=", "text"]),
parsingContext: new ParsingContext() searchContext: new SearchContext()
}); });
expect(rootExp.constructor.name).toEqual("OrExp"); expect(rootExp.constructor.name).toEqual("OrExp");
@ -147,7 +147,7 @@ describe("Parser", () => {
const rootExp = parse({ const rootExp = parse({
fulltextTokens: tokens(["hello"]), fulltextTokens: tokens(["hello"]),
expressionTokens: tokens(["#mylabel", "=", "text"]), expressionTokens: tokens(["#mylabel", "=", "text"]),
parsingContext: new ParsingContext() searchContext: new SearchContext()
}); });
expect(rootExp.constructor.name).toEqual("AndExp"); expect(rootExp.constructor.name).toEqual("AndExp");
@ -165,7 +165,7 @@ describe("Parser", () => {
const rootExp = parse({ const rootExp = parse({
fulltextTokens: [], fulltextTokens: [],
expressionTokens: tokens(["#first", "=", "text", "or", ["#second", "=", "text", "and", "#third", "=", "text"]]), expressionTokens: tokens(["#first", "=", "text", "or", ["#second", "=", "text", "and", "#third", "=", "text"]]),
parsingContext: new ParsingContext() searchContext: new SearchContext()
}); });
expect(rootExp.constructor.name).toEqual("OrExp"); expect(rootExp.constructor.name).toEqual("OrExp");
@ -187,39 +187,39 @@ describe("Parser", () => {
describe("Invalid expressions", () => { describe("Invalid expressions", () => {
it("incomplete comparison", () => { it("incomplete comparison", () => {
const parsingContext = new ParsingContext(); const searchContext = new SearchContext();
parse({ parse({
fulltextTokens: [], fulltextTokens: [],
expressionTokens: tokens(["#first", "="]), expressionTokens: tokens(["#first", "="]),
parsingContext searchContext
}); });
expect(parsingContext.error).toEqual('Misplaced or incomplete expression "="') expect(searchContext.error).toEqual('Misplaced or incomplete expression "="')
}); });
it("comparison between labels is impossible", () => { it("comparison between labels is impossible", () => {
let parsingContext = new ParsingContext(); let searchContext = new SearchContext();
parsingContext.originalQuery = "#first = #second"; searchContext.originalQuery = "#first = #second";
parse({ parse({
fulltextTokens: [], fulltextTokens: [],
expressionTokens: tokens(["#first", "=", "#second"]), expressionTokens: tokens(["#first", "=", "#second"]),
parsingContext searchContext
}); });
expect(parsingContext.error).toEqual(`Error near token "#second" in "#first = #second", it's possible to compare with constant only.`); expect(searchContext.error).toEqual(`Error near token "#second" in "#first = #second", it's possible to compare with constant only.`);
parsingContext = new ParsingContext(); searchContext = new SearchContext();
parsingContext.originalQuery = "#first = note.relations.second"; searchContext.originalQuery = "#first = note.relations.second";
parse({ parse({
fulltextTokens: [], fulltextTokens: [],
expressionTokens: tokens(["#first", "=", "note", ".", "relations", "second"]), expressionTokens: tokens(["#first", "=", "note", ".", "relations", "second"]),
parsingContext searchContext
}); });
expect(parsingContext.error).toEqual(`Error near token "note" in "#first = note.relations.second", it's possible to compare with constant only.`); expect(searchContext.error).toEqual(`Error near token "note" in "#first = note.relations.second", it's possible to compare with constant only.`);
const rootExp = parse({ const rootExp = parse({
fulltextTokens: [], fulltextTokens: [],
@ -228,7 +228,7 @@ describe("Invalid expressions", () => {
{ token: "=", inQuotes: false }, { token: "=", inQuotes: false },
{ token: "#second", inQuotes: true }, { token: "#second", inQuotes: true },
], ],
parsingContext: new ParsingContext() searchContext: new SearchContext()
}); });
expect(rootExp.constructor.name).toEqual("LabelComparisonExp"); expect(rootExp.constructor.name).toEqual("LabelComparisonExp");

View File

@ -1,7 +1,7 @@
const searchService = require('../../src/services/search/services/search.js'); const searchService = require('../../src/services/search/services/search.js');
const Note = require('../../src/services/note_cache/entities/note.js'); const Note = require('../../src/services/note_cache/entities/note.js');
const Branch = require('../../src/services/note_cache/entities/branch.js'); const Branch = require('../../src/services/note_cache/entities/branch.js');
const ParsingContext = require('../../src/services/search/parsing_context.js'); const SearchContext = require('../../src/services/search/search_context.js');
const dateUtils = require('../../src/services/date_utils.js'); const dateUtils = require('../../src/services/date_utils.js');
const noteCache = require('../../src/services/note_cache/note_cache.js'); const noteCache = require('../../src/services/note_cache/note_cache.js');
const {NoteBuilder, findNoteByTitle, note} = require('./note_cache_mocking.js'); const {NoteBuilder, findNoteByTitle, note} = require('./note_cache_mocking.js');
@ -22,8 +22,8 @@ describe("Search", () => {
.child(note("Austria")) .child(note("Austria"))
); );
const parsingContext = new ParsingContext(); const searchContext = new SearchContext();
const searchResults = searchService.findNotesWithQuery('europe austria', parsingContext); const searchResults = searchService.findNotesWithQuery('europe austria', searchContext);
expect(searchResults.length).toEqual(1); expect(searchResults.length).toEqual(1);
expect(findNoteByTitle(searchResults, "Austria")).toBeTruthy(); expect(findNoteByTitle(searchResults, "Austria")).toBeTruthy();
@ -39,13 +39,13 @@ describe("Search", () => {
.child(vienna .child(vienna
.label('inhabitants', '1888776')); .label('inhabitants', '1888776'));
const parsingContext = new ParsingContext(); const searchContext = new SearchContext();
let searchResults = searchService.findNotesWithQuery('capital', parsingContext); let searchResults = searchService.findNotesWithQuery('capital', searchContext);
expect(searchResults.length).toEqual(1); expect(searchResults.length).toEqual(1);
expect(findNoteByTitle(searchResults, "Austria")).toBeTruthy(); expect(findNoteByTitle(searchResults, "Austria")).toBeTruthy();
searchResults = searchService.findNotesWithQuery('inhabitants', parsingContext); searchResults = searchService.findNotesWithQuery('inhabitants', searchContext);
expect(searchResults.length).toEqual(1); expect(searchResults.length).toEqual(1);
expect(findNoteByTitle(searchResults, "Vienna")).toBeTruthy(); expect(findNoteByTitle(searchResults, "Vienna")).toBeTruthy();
@ -56,18 +56,18 @@ describe("Search", () => {
.child(note("Effective Java", 'book', '')) .child(note("Effective Java", 'book', ''))
.child(note("Hello World.java", 'code', 'text/x-java')); .child(note("Hello World.java", 'code', 'text/x-java'));
const parsingContext = new ParsingContext(); const searchContext = new SearchContext();
let searchResults = searchService.findNotesWithQuery('book', parsingContext); let searchResults = searchService.findNotesWithQuery('book', searchContext);
expect(searchResults.length).toEqual(1); expect(searchResults.length).toEqual(1);
expect(findNoteByTitle(searchResults, "Effective Java")).toBeTruthy(); expect(findNoteByTitle(searchResults, "Effective Java")).toBeTruthy();
searchResults = searchService.findNotesWithQuery('text', parsingContext); // should match mime searchResults = searchService.findNotesWithQuery('text', searchContext); // should match mime
expect(searchResults.length).toEqual(1); expect(searchResults.length).toEqual(1);
expect(findNoteByTitle(searchResults, "Hello World.java")).toBeTruthy(); expect(findNoteByTitle(searchResults, "Hello World.java")).toBeTruthy();
searchResults = searchService.findNotesWithQuery('java', parsingContext); searchResults = searchService.findNotesWithQuery('java', searchContext);
expect(searchResults.length).toEqual(2); expect(searchResults.length).toEqual(2);
}); });
@ -78,8 +78,8 @@ describe("Search", () => {
.child(note("Austria")) .child(note("Austria"))
); );
const parsingContext = new ParsingContext(); const searchContext = new SearchContext();
const searchResults = searchService.findNotesWithQuery('europe', parsingContext); const searchResults = searchService.findNotesWithQuery('europe', searchContext);
expect(searchResults.length).toEqual(1); expect(searchResults.length).toEqual(1);
expect(findNoteByTitle(searchResults, "Europe")).toBeTruthy(); expect(findNoteByTitle(searchResults, "Europe")).toBeTruthy();
@ -92,9 +92,9 @@ describe("Search", () => {
.label('capital', 'Vienna')) .label('capital', 'Vienna'))
); );
const parsingContext = new ParsingContext(); const searchContext = new SearchContext();
const searchResults = searchService.findNotesWithQuery('Vienna', parsingContext); const searchResults = searchService.findNotesWithQuery('Vienna', searchContext);
expect(searchResults.length).toEqual(1); expect(searchResults.length).toEqual(1);
expect(findNoteByTitle(searchResults, "Austria")).toBeTruthy(); expect(findNoteByTitle(searchResults, "Austria")).toBeTruthy();
}); });
@ -108,9 +108,9 @@ describe("Search", () => {
.label('capital', 'Prague')) .label('capital', 'Prague'))
); );
const parsingContext = new ParsingContext(); const searchContext = new SearchContext();
let searchResults = searchService.findNotesWithQuery('#capital=Vienna', parsingContext); let searchResults = searchService.findNotesWithQuery('#capital=Vienna', searchContext);
expect(searchResults.length).toEqual(1); expect(searchResults.length).toEqual(1);
expect(findNoteByTitle(searchResults, "Austria")).toBeTruthy(); expect(findNoteByTitle(searchResults, "Austria")).toBeTruthy();
}); });
@ -124,9 +124,9 @@ describe("Search", () => {
.label('capital', 'Prague')) .label('capital', 'Prague'))
); );
const parsingContext = new ParsingContext(); const searchContext = new SearchContext();
let searchResults = searchService.findNotesWithQuery('# note.labels.capital=Prague', parsingContext); let searchResults = searchService.findNotesWithQuery('# note.labels.capital=Prague', searchContext);
expect(searchResults.length).toEqual(1); expect(searchResults.length).toEqual(1);
expect(findNoteByTitle(searchResults, "Czech Republic")).toBeTruthy(); expect(findNoteByTitle(searchResults, "Czech Republic")).toBeTruthy();
}); });
@ -141,9 +141,9 @@ describe("Search", () => {
.label('population', '10650000')) .label('population', '10650000'))
); );
const parsingContext = new ParsingContext(); const searchContext = new SearchContext();
const searchResults = searchService.findNotesWithQuery('#country #population >= 10000000', parsingContext); const searchResults = searchService.findNotesWithQuery('#country #population >= 10000000', searchContext);
expect(searchResults.length).toEqual(1); expect(searchResults.length).toEqual(1);
expect(findNoteByTitle(searchResults, "Czech Republic")).toBeTruthy(); expect(findNoteByTitle(searchResults, "Czech Republic")).toBeTruthy();
}); });
@ -162,13 +162,13 @@ describe("Search", () => {
.label('established', '1920-06-04')) .label('established', '1920-06-04'))
); );
const parsingContext = new ParsingContext(); const searchContext = new SearchContext();
let searchResults = searchService.findNotesWithQuery('#established <= "1955-01-01"', parsingContext); let searchResults = searchService.findNotesWithQuery('#established <= "1955-01-01"', searchContext);
expect(searchResults.length).toEqual(1); expect(searchResults.length).toEqual(1);
expect(findNoteByTitle(searchResults, "Hungary")).toBeTruthy(); expect(findNoteByTitle(searchResults, "Hungary")).toBeTruthy();
searchResults = searchService.findNotesWithQuery('#established > "1955-01-01"', parsingContext); searchResults = searchService.findNotesWithQuery('#established > "1955-01-01"', searchContext);
expect(searchResults.length).toEqual(2); expect(searchResults.length).toEqual(2);
expect(findNoteByTitle(searchResults, "Austria")).toBeTruthy(); expect(findNoteByTitle(searchResults, "Austria")).toBeTruthy();
expect(findNoteByTitle(searchResults, "Czech Republic")).toBeTruthy(); expect(findNoteByTitle(searchResults, "Czech Republic")).toBeTruthy();
@ -185,10 +185,10 @@ describe("Search", () => {
.label('dateTime', dateUtils.localNowDateTime()) .label('dateTime', dateUtils.localNowDateTime())
); );
const parsingContext = new ParsingContext(); const searchContext = new SearchContext();
function test(query, expectedResultCount) { function test(query, expectedResultCount) {
const searchResults = searchService.findNotesWithQuery(query, parsingContext); const searchResults = searchService.findNotesWithQuery(query, searchContext);
expect(searchResults.length).toEqual(expectedResultCount); expect(searchResults.length).toEqual(expectedResultCount);
if (expectedResultCount === 1) { if (expectedResultCount === 1) {
@ -238,9 +238,9 @@ describe("Search", () => {
.label('languageFamily', 'finnougric')) .label('languageFamily', 'finnougric'))
); );
const parsingContext = new ParsingContext(); const searchContext = new SearchContext();
const searchResults = searchService.findNotesWithQuery('#languageFamily = slavic OR #languageFamily = germanic', parsingContext); const searchResults = searchService.findNotesWithQuery('#languageFamily = slavic OR #languageFamily = germanic', searchContext);
expect(searchResults.length).toEqual(2); expect(searchResults.length).toEqual(2);
expect(findNoteByTitle(searchResults, "Czech Republic")).toBeTruthy(); expect(findNoteByTitle(searchResults, "Czech Republic")).toBeTruthy();
expect(findNoteByTitle(searchResults, "Austria")).toBeTruthy(); expect(findNoteByTitle(searchResults, "Austria")).toBeTruthy();
@ -255,20 +255,20 @@ describe("Search", () => {
.child(note("Czech Republic") .child(note("Czech Republic")
.label('languageFamily', 'slavic'))); .label('languageFamily', 'slavic')));
let parsingContext = new ParsingContext({fuzzyAttributeSearch: false}); let searchContext = new SearchContext({fuzzyAttributeSearch: false});
let searchResults = searchService.findNotesWithQuery('#language', parsingContext); let searchResults = searchService.findNotesWithQuery('#language', searchContext);
expect(searchResults.length).toEqual(0); expect(searchResults.length).toEqual(0);
searchResults = searchService.findNotesWithQuery('#languageFamily=ger', parsingContext); searchResults = searchService.findNotesWithQuery('#languageFamily=ger', searchContext);
expect(searchResults.length).toEqual(0); expect(searchResults.length).toEqual(0);
parsingContext = new ParsingContext({fuzzyAttributeSearch: true}); searchContext = new SearchContext({fuzzyAttributeSearch: true});
searchResults = searchService.findNotesWithQuery('#language', parsingContext); searchResults = searchService.findNotesWithQuery('#language', searchContext);
expect(searchResults.length).toEqual(2); expect(searchResults.length).toEqual(2);
searchResults = searchService.findNotesWithQuery('#languageFamily=ger', parsingContext); searchResults = searchService.findNotesWithQuery('#languageFamily=ger', searchContext);
expect(searchResults.length).toEqual(1); expect(searchResults.length).toEqual(1);
expect(findNoteByTitle(searchResults, "Austria")).toBeTruthy(); expect(findNoteByTitle(searchResults, "Austria")).toBeTruthy();
}); });
@ -279,9 +279,9 @@ describe("Search", () => {
.child(note("Austria")) .child(note("Austria"))
.child(note("Czech Republic"))); .child(note("Czech Republic")));
const parsingContext = new ParsingContext(); const searchContext = new SearchContext();
const searchResults = searchService.findNotesWithQuery('# note.title =* czech', parsingContext); const searchResults = searchService.findNotesWithQuery('# note.title =* czech', searchContext);
expect(searchResults.length).toEqual(1); expect(searchResults.length).toEqual(1);
expect(findNoteByTitle(searchResults, "Czech Republic")).toBeTruthy(); expect(findNoteByTitle(searchResults, "Czech Republic")).toBeTruthy();
}); });
@ -296,18 +296,18 @@ describe("Search", () => {
.child(note("Asia") .child(note("Asia")
.child(note('Taiwan'))); .child(note('Taiwan')));
const parsingContext = new ParsingContext(); const searchContext = new SearchContext();
let searchResults = searchService.findNotesWithQuery('# note.parents.title = Europe', parsingContext); let searchResults = searchService.findNotesWithQuery('# note.parents.title = Europe', searchContext);
expect(searchResults.length).toEqual(2); expect(searchResults.length).toEqual(2);
expect(findNoteByTitle(searchResults, "Austria")).toBeTruthy(); expect(findNoteByTitle(searchResults, "Austria")).toBeTruthy();
expect(findNoteByTitle(searchResults, "Czech Republic")).toBeTruthy(); expect(findNoteByTitle(searchResults, "Czech Republic")).toBeTruthy();
searchResults = searchService.findNotesWithQuery('# note.parents.title = Asia', parsingContext); searchResults = searchService.findNotesWithQuery('# note.parents.title = Asia', searchContext);
expect(searchResults.length).toEqual(1); expect(searchResults.length).toEqual(1);
expect(findNoteByTitle(searchResults, "Taiwan")).toBeTruthy(); expect(findNoteByTitle(searchResults, "Taiwan")).toBeTruthy();
searchResults = searchService.findNotesWithQuery('# note.parents.parents.title = Europe', parsingContext); searchResults = searchService.findNotesWithQuery('# note.parents.parents.title = Europe', searchContext);
expect(searchResults.length).toEqual(1); expect(searchResults.length).toEqual(1);
expect(findNoteByTitle(searchResults, "Prague")).toBeTruthy(); expect(findNoteByTitle(searchResults, "Prague")).toBeTruthy();
}); });
@ -324,13 +324,13 @@ describe("Search", () => {
.child(note('Taipei').label('city'))) .child(note('Taipei').label('city')))
); );
const parsingContext = new ParsingContext(); const searchContext = new SearchContext();
let searchResults = searchService.findNotesWithQuery('#city AND note.ancestors.title = Europe', parsingContext); let searchResults = searchService.findNotesWithQuery('#city AND note.ancestors.title = Europe', searchContext);
expect(searchResults.length).toEqual(1); expect(searchResults.length).toEqual(1);
expect(findNoteByTitle(searchResults, "Prague")).toBeTruthy(); expect(findNoteByTitle(searchResults, "Prague")).toBeTruthy();
searchResults = searchService.findNotesWithQuery('#city AND note.ancestors.title = Asia', parsingContext); searchResults = searchService.findNotesWithQuery('#city AND note.ancestors.title = Asia', searchContext);
expect(searchResults.length).toEqual(1); expect(searchResults.length).toEqual(1);
expect(findNoteByTitle(searchResults, "Taipei")).toBeTruthy(); expect(findNoteByTitle(searchResults, "Taipei")).toBeTruthy();
}); });
@ -345,18 +345,18 @@ describe("Search", () => {
.child(note("Oceania") .child(note("Oceania")
.child(note('Australia'))); .child(note('Australia')));
const parsingContext = new ParsingContext(); const searchContext = new SearchContext();
let searchResults = searchService.findNotesWithQuery('# note.children.title =* Aust', parsingContext); let searchResults = searchService.findNotesWithQuery('# note.children.title =* Aust', searchContext);
expect(searchResults.length).toEqual(2); expect(searchResults.length).toEqual(2);
expect(findNoteByTitle(searchResults, "Europe")).toBeTruthy(); expect(findNoteByTitle(searchResults, "Europe")).toBeTruthy();
expect(findNoteByTitle(searchResults, "Oceania")).toBeTruthy(); expect(findNoteByTitle(searchResults, "Oceania")).toBeTruthy();
searchResults = searchService.findNotesWithQuery('# note.children.title =* Aust AND note.children.title *= republic', parsingContext); searchResults = searchService.findNotesWithQuery('# note.children.title =* Aust AND note.children.title *= republic', searchContext);
expect(searchResults.length).toEqual(1); expect(searchResults.length).toEqual(1);
expect(findNoteByTitle(searchResults, "Europe")).toBeTruthy(); expect(findNoteByTitle(searchResults, "Europe")).toBeTruthy();
searchResults = searchService.findNotesWithQuery('# note.children.children.title = Prague', parsingContext); searchResults = searchService.findNotesWithQuery('# note.children.children.title = Prague', searchContext);
expect(searchResults.length).toEqual(1); expect(searchResults.length).toEqual(1);
expect(findNoteByTitle(searchResults, "Europe")).toBeTruthy(); expect(findNoteByTitle(searchResults, "Europe")).toBeTruthy();
}); });
@ -375,13 +375,13 @@ describe("Search", () => {
.relation('neighbor', portugal.note)) .relation('neighbor', portugal.note))
); );
const parsingContext = new ParsingContext(); const searchContext = new SearchContext();
let searchResults = searchService.findNotesWithQuery('# ~neighbor.title = Austria', parsingContext); let searchResults = searchService.findNotesWithQuery('# ~neighbor.title = Austria', searchContext);
expect(searchResults.length).toEqual(1); expect(searchResults.length).toEqual(1);
expect(findNoteByTitle(searchResults, "Czech Republic")).toBeTruthy(); expect(findNoteByTitle(searchResults, "Czech Republic")).toBeTruthy();
searchResults = searchService.findNotesWithQuery('# ~neighbor.title = Portugal', parsingContext); searchResults = searchService.findNotesWithQuery('# ~neighbor.title = Portugal', searchContext);
expect(searchResults.length).toEqual(1); expect(searchResults.length).toEqual(1);
expect(findNoteByTitle(searchResults, "Spain")).toBeTruthy(); expect(findNoteByTitle(searchResults, "Spain")).toBeTruthy();
}); });
@ -400,9 +400,9 @@ describe("Search", () => {
.relation('neighbor', portugal.note)) .relation('neighbor', portugal.note))
); );
const parsingContext = new ParsingContext(); const searchContext = new SearchContext();
const searchResults = searchService.findNotesWithQuery('# note.relations.neighbor.title = Austria', parsingContext); const searchResults = searchService.findNotesWithQuery('# note.relations.neighbor.title = Austria', searchContext);
expect(searchResults.length).toEqual(1); expect(searchResults.length).toEqual(1);
expect(findNoteByTitle(searchResults, "Czech Republic")).toBeTruthy(); expect(findNoteByTitle(searchResults, "Czech Republic")).toBeTruthy();
}); });
@ -426,13 +426,13 @@ describe("Search", () => {
.child(ukraine) .child(ukraine)
); );
const parsingContext = new ParsingContext(); const searchContext = new SearchContext();
let searchResults = searchService.findNotesWithQuery('# note.relations.neighbor.relations.neighbor.title = Italy', parsingContext); let searchResults = searchService.findNotesWithQuery('# note.relations.neighbor.relations.neighbor.title = Italy', searchContext);
expect(searchResults.length).toEqual(1); expect(searchResults.length).toEqual(1);
expect(findNoteByTitle(searchResults, "Czech Republic")).toBeTruthy(); expect(findNoteByTitle(searchResults, "Czech Republic")).toBeTruthy();
searchResults = searchService.findNotesWithQuery('# note.relations.neighbor.relations.neighbor.title = Ukraine', parsingContext); searchResults = searchService.findNotesWithQuery('# note.relations.neighbor.relations.neighbor.title = Ukraine', searchContext);
expect(searchResults.length).toEqual(2); expect(searchResults.length).toEqual(2);
expect(findNoteByTitle(searchResults, "Czech Republic")).toBeTruthy(); expect(findNoteByTitle(searchResults, "Czech Republic")).toBeTruthy();
expect(findNoteByTitle(searchResults, "Austria")).toBeTruthy(); expect(findNoteByTitle(searchResults, "Austria")).toBeTruthy();
@ -463,10 +463,10 @@ describe("Search", () => {
austria.note.utcDateModified = '2020-05-14 11:11:42.001Z'; austria.note.utcDateModified = '2020-05-14 11:11:42.001Z';
austria.note.contentLength = 1001; austria.note.contentLength = 1001;
const parsingContext = new ParsingContext(); const searchContext = new SearchContext();
function test(propertyName, value, expectedResultCount) { function test(propertyName, value, expectedResultCount) {
const searchResults = searchService.findNotesWithQuery(`# note.${propertyName} = ${value}`, parsingContext); const searchResults = searchService.findNotesWithQuery(`# note.${propertyName} = ${value}`, searchContext);
expect(searchResults.length).toEqual(expectedResultCount); expect(searchResults.length).toEqual(expectedResultCount);
} }
@ -520,38 +520,38 @@ describe("Search", () => {
.child(austria) .child(austria)
.child(italy)); .child(italy));
const parsingContext = new ParsingContext(); const searchContext = new SearchContext();
let searchResults = searchService.findNotesWithQuery('# note.parents.title = Europe orderBy note.title', parsingContext); let searchResults = searchService.findNotesWithQuery('# note.parents.title = Europe orderBy note.title', searchContext);
expect(searchResults.length).toEqual(4); expect(searchResults.length).toEqual(4);
expect(noteCache.notes[searchResults[0].noteId].title).toEqual("Austria"); expect(noteCache.notes[searchResults[0].noteId].title).toEqual("Austria");
expect(noteCache.notes[searchResults[1].noteId].title).toEqual("Italy"); expect(noteCache.notes[searchResults[1].noteId].title).toEqual("Italy");
expect(noteCache.notes[searchResults[2].noteId].title).toEqual("Slovakia"); expect(noteCache.notes[searchResults[2].noteId].title).toEqual("Slovakia");
expect(noteCache.notes[searchResults[3].noteId].title).toEqual("Ukraine"); expect(noteCache.notes[searchResults[3].noteId].title).toEqual("Ukraine");
searchResults = searchService.findNotesWithQuery('# note.parents.title = Europe orderBy note.labels.capital', parsingContext); searchResults = searchService.findNotesWithQuery('# note.parents.title = Europe orderBy note.labels.capital', searchContext);
expect(searchResults.length).toEqual(4); expect(searchResults.length).toEqual(4);
expect(noteCache.notes[searchResults[0].noteId].title).toEqual("Slovakia"); expect(noteCache.notes[searchResults[0].noteId].title).toEqual("Slovakia");
expect(noteCache.notes[searchResults[1].noteId].title).toEqual("Ukraine"); expect(noteCache.notes[searchResults[1].noteId].title).toEqual("Ukraine");
expect(noteCache.notes[searchResults[2].noteId].title).toEqual("Italy"); expect(noteCache.notes[searchResults[2].noteId].title).toEqual("Italy");
expect(noteCache.notes[searchResults[3].noteId].title).toEqual("Austria"); expect(noteCache.notes[searchResults[3].noteId].title).toEqual("Austria");
searchResults = searchService.findNotesWithQuery('# note.parents.title = Europe orderBy note.labels.capital DESC', parsingContext); searchResults = searchService.findNotesWithQuery('# note.parents.title = Europe orderBy note.labels.capital DESC', searchContext);
expect(searchResults.length).toEqual(4); expect(searchResults.length).toEqual(4);
expect(noteCache.notes[searchResults[0].noteId].title).toEqual("Austria"); expect(noteCache.notes[searchResults[0].noteId].title).toEqual("Austria");
expect(noteCache.notes[searchResults[1].noteId].title).toEqual("Italy"); expect(noteCache.notes[searchResults[1].noteId].title).toEqual("Italy");
expect(noteCache.notes[searchResults[2].noteId].title).toEqual("Ukraine"); expect(noteCache.notes[searchResults[2].noteId].title).toEqual("Ukraine");
expect(noteCache.notes[searchResults[3].noteId].title).toEqual("Slovakia"); expect(noteCache.notes[searchResults[3].noteId].title).toEqual("Slovakia");
searchResults = searchService.findNotesWithQuery('# note.parents.title = Europe orderBy note.labels.capital DESC limit 2', parsingContext); searchResults = searchService.findNotesWithQuery('# note.parents.title = Europe orderBy note.labels.capital DESC limit 2', searchContext);
expect(searchResults.length).toEqual(2); expect(searchResults.length).toEqual(2);
expect(noteCache.notes[searchResults[0].noteId].title).toEqual("Austria"); expect(noteCache.notes[searchResults[0].noteId].title).toEqual("Austria");
expect(noteCache.notes[searchResults[1].noteId].title).toEqual("Italy"); expect(noteCache.notes[searchResults[1].noteId].title).toEqual("Italy");
searchResults = searchService.findNotesWithQuery('# note.parents.title = Europe orderBy #capital DESC limit 0', parsingContext); searchResults = searchService.findNotesWithQuery('# note.parents.title = Europe orderBy #capital DESC limit 0', searchContext);
expect(searchResults.length).toEqual(0); expect(searchResults.length).toEqual(0);
searchResults = searchService.findNotesWithQuery('# note.parents.title = Europe orderBy #capital DESC limit 1000', parsingContext); searchResults = searchService.findNotesWithQuery('# note.parents.title = Europe orderBy #capital DESC limit 1000', searchContext);
expect(searchResults.length).toEqual(4); expect(searchResults.length).toEqual(4);
}); });
@ -564,13 +564,13 @@ describe("Search", () => {
.child(slovakia) .child(slovakia)
.child(italy)); .child(italy));
const parsingContext = new ParsingContext(); const searchContext = new SearchContext();
let searchResults = searchService.findNotesWithQuery('# not(#capital) and note.noteId != root', parsingContext); let searchResults = searchService.findNotesWithQuery('# not(#capital) and note.noteId != root', searchContext);
expect(searchResults.length).toEqual(1); expect(searchResults.length).toEqual(1);
expect(noteCache.notes[searchResults[0].noteId].title).toEqual("Europe"); expect(noteCache.notes[searchResults[0].noteId].title).toEqual("Europe");
searchResults = searchService.findNotesWithQuery('#!capital and note.noteId != root', parsingContext); searchResults = searchService.findNotesWithQuery('#!capital and note.noteId != root', searchContext);
expect(searchResults.length).toEqual(1); expect(searchResults.length).toEqual(1);
expect(noteCache.notes[searchResults[0].noteId].title).toEqual("Europe"); expect(noteCache.notes[searchResults[0].noteId].title).toEqual("Europe");
}); });
@ -584,9 +584,9 @@ describe("Search", () => {
.child(slovakia) .child(slovakia)
.child(italy)); .child(italy));
const parsingContext = new ParsingContext(); const searchContext = new SearchContext();
let searchResults = searchService.findNotesWithQuery('# note.text *=* rati and note.noteId != root', parsingContext); let searchResults = searchService.findNotesWithQuery('# note.text *=* rati and note.noteId != root', searchContext);
expect(searchResults.length).toEqual(1); expect(searchResults.length).toEqual(1);
expect(noteCache.notes[searchResults[0].noteId].title).toEqual("Slovakia"); expect(noteCache.notes[searchResults[0].noteId].title).toEqual("Slovakia");
}); });
@ -601,9 +601,9 @@ describe("Search", () => {
.child(note('Post Y'))) .child(note('Post Y')))
.child(note ('Reddit is bad')); .child(note ('Reddit is bad'));
const parsingContext = new ParsingContext(); const searchContext = new SearchContext();
let searchResults = searchService.findNotesWithQuery('reddit', parsingContext); let searchResults = searchService.findNotesWithQuery('reddit', searchContext);
expect(searchResults.length).toEqual(1); expect(searchResults.length).toEqual(1);
expect(noteCache.notes[searchResults[0].noteId].title).toEqual("Reddit is bad"); expect(noteCache.notes[searchResults[0].noteId].title).toEqual("Reddit is bad");
}); });
@ -624,9 +624,9 @@ describe("Search", () => {
// .label('largestCity', 'Prague')) // .label('largestCity', 'Prague'))
// ); // );
// //
// const parsingContext = new ParsingContext(); // const searchContext = new SearchContext();
// //
// const searchResults = searchService.findNotesWithQuery('#capital = #largestCity', parsingContext); // const searchResults = searchService.findNotesWithQuery('#capital = #largestCity', searchContext);
// expect(searchResults.length).toEqual(2); // expect(searchResults.length).toEqual(2);
// expect(findNoteByTitle(searchResults, "Czech Republic")).toBeTruthy(); // expect(findNoteByTitle(searchResults, "Czech Republic")).toBeTruthy();
// expect(findNoteByTitle(searchResults, "Austria")).toBeTruthy(); // expect(findNoteByTitle(searchResults, "Austria")).toBeTruthy();

View File

@ -1,19 +1,19 @@
"use strict"; "use strict";
const repository = require('../../services/repository'); const repository = require('../../services/repository');
const ParsingContext = require('../../services/search/parsing_context'); const SearchContext = require('../../services/search/search_context.js');
const log = require('../../services/log'); const log = require('../../services/log');
const scriptService = require('../../services/script'); const scriptService = require('../../services/script');
const searchService = require('../../services/search/services/search'); const searchService = require('../../services/search/services/search');
function searchNotes(req) { function searchNotes(req) {
const parsingContext = new ParsingContext({ const searchContext = new SearchContext({
includeNoteContent: req.query.includeNoteContent === 'true', includeNoteContent: req.query.includeNoteContent === 'true',
excludeArchived: req.query.excludeArchived === 'true', excludeArchived: req.query.excludeArchived === 'true',
fuzzyAttributeSearch: req.query.fuzzyAttributeSearch === 'true' fuzzyAttributeSearch: req.query.fuzzyAttributeSearch === 'true'
}); });
const {count, results} = searchService.searchTrimmedNotes(req.params.searchString, parsingContext); const {count, results} = searchService.searchTrimmedNotes(req.params.searchString, searchContext);
try { try {
return { return {

View File

@ -12,7 +12,7 @@ const dayjs = require('dayjs');
const cloningService = require('./cloning'); const cloningService = require('./cloning');
const appInfo = require('./app_info'); const appInfo = require('./app_info');
const searchService = require('./search/services/search'); const searchService = require('./search/services/search');
const ParsingContext = require("./search/parsing_context"); const SearchContext = require("./search/search_context.js");
/** /**
* This is the main backend API interface for scripts. It's published in the local "api" object. * This is the main backend API interface for scripts. It's published in the local "api" object.
@ -92,13 +92,13 @@ function BackendScriptApi(currentNote, apiParams) {
* *
* @method * @method
* @param {string} query * @param {string} query
* @param {ParsingContext} [parsingContext] * @param {SearchContext} [searchContext]
* @returns {Note[]} * @returns {Note[]}
*/ */
this.searchForNotes = (query, parsingContext) => { this.searchForNotes = (query, searchContext) => {
parsingContext = parsingContext || new ParsingContext(); searchContext = searchContext || new SearchContext();
const noteIds = searchService.findNotesWithQuery(query, parsingContext) const noteIds = searchService.findNotesWithQuery(query, searchContext)
.map(sr => sr.noteId); .map(sr => sr.noteId);
return repository.getNotes(noteIds); return repository.getNotes(noteIds);

View File

@ -1,6 +1,6 @@
"use strict"; "use strict";
class ParsingContext { class SearchContext {
constructor(params = {}) { constructor(params = {}) {
this.includeNoteContent = !!params.includeNoteContent; this.includeNoteContent = !!params.includeNoteContent;
this.excludeArchived = !!params.excludeArchived; this.excludeArchived = !!params.excludeArchived;
@ -18,4 +18,4 @@ class ParsingContext {
} }
} }
module.exports = ParsingContext; module.exports = SearchContext;

View File

@ -18,16 +18,16 @@ const OrderByAndLimitExp = require('../expressions/order_by_and_limit.js');
const buildComparator = require('./build_comparator.js'); const buildComparator = require('./build_comparator.js');
const ValueExtractor = require('../value_extractor.js'); const ValueExtractor = require('../value_extractor.js');
function getFulltext(tokens, parsingContext) { function getFulltext(tokens, searchContext) {
tokens = tokens.map(t => t.token); tokens = tokens.map(t => t.token);
parsingContext.highlightedTokens.push(...tokens); searchContext.highlightedTokens.push(...tokens);
if (tokens.length === 0) { if (tokens.length === 0) {
return null; return null;
} }
if (parsingContext.includeNoteContent) { if (searchContext.includeNoteContent) {
return new OrExp([ return new OrExp([
new NoteCacheFulltextExp(tokens), new NoteCacheFulltextExp(tokens),
new NoteContentProtectedFulltextExp('*=*', tokens), new NoteContentProtectedFulltextExp('*=*', tokens),
@ -43,7 +43,7 @@ function isOperator(str) {
return str.match(/^[=<>*]+$/); return str.match(/^[=<>*]+$/);
} }
function getExpression(tokens, parsingContext, level = 0) { function getExpression(tokens, searchContext, level = 0) {
if (tokens.length === 0) { if (tokens.length === 0) {
return null; return null;
} }
@ -56,11 +56,11 @@ function getExpression(tokens, parsingContext, level = 0) {
function context(i) { function context(i) {
let {startIndex, endIndex} = tokens[i]; let {startIndex, endIndex} = tokens[i];
startIndex = Math.max(0, startIndex - 20); startIndex = Math.max(0, startIndex - 20);
endIndex = Math.min(parsingContext.originalQuery.length, endIndex + 20); endIndex = Math.min(searchContext.originalQuery.length, endIndex + 20);
return '"' + (startIndex !== 0 ? "..." : "") return '"' + (startIndex !== 0 ? "..." : "")
+ parsingContext.originalQuery.substr(startIndex, endIndex - startIndex) + searchContext.originalQuery.substr(startIndex, endIndex - startIndex)
+ (endIndex !== parsingContext.originalQuery.length ? "..." : "") + '"'; + (endIndex !== searchContext.originalQuery.length ? "..." : "") + '"';
} }
function resolveConstantOperand() { function resolveConstantOperand() {
@ -68,7 +68,7 @@ function getExpression(tokens, parsingContext, level = 0) {
if (!operand.inQuotes if (!operand.inQuotes
&& (operand.token.startsWith('#') || operand.token.startsWith('~') || operand.token === 'note')) { && (operand.token.startsWith('#') || operand.token.startsWith('~') || operand.token === 'note')) {
parsingContext.addError(`Error near token "${operand.token}" in ${context(i)}, it's possible to compare with constant only.`); searchContext.addError(`Error near token "${operand.token}" in ${context(i)}, it's possible to compare with constant only.`);
return null; return null;
} }
@ -114,7 +114,7 @@ function getExpression(tokens, parsingContext, level = 0) {
function parseNoteProperty() { function parseNoteProperty() {
if (tokens[i].token !== '.') { if (tokens[i].token !== '.') {
parsingContext.addError('Expected "." to separate field path'); searchContext.addError('Expected "." to separate field path');
return; return;
} }
@ -126,7 +126,7 @@ function getExpression(tokens, parsingContext, level = 0) {
const operator = tokens[i].token; const operator = tokens[i].token;
if (!isOperator(operator)) { if (!isOperator(operator)) {
parsingContext.addError(`After content expected operator, but got "${tokens[i].token}" in ${context(i)}`); searchContext.addError(`After content expected operator, but got "${tokens[i].token}" in ${context(i)}`);
return; return;
} }
@ -158,7 +158,7 @@ function getExpression(tokens, parsingContext, level = 0) {
if (tokens[i].token === 'labels') { if (tokens[i].token === 'labels') {
if (tokens[i + 1].token !== '.') { if (tokens[i + 1].token !== '.') {
parsingContext.addError(`Expected "." to separate field path, got "${tokens[i + 1].token}" in ${context(i)}`); searchContext.addError(`Expected "." to separate field path, got "${tokens[i + 1].token}" in ${context(i)}`);
return; return;
} }
@ -169,7 +169,7 @@ function getExpression(tokens, parsingContext, level = 0) {
if (tokens[i].token === 'relations') { if (tokens[i].token === 'relations') {
if (tokens[i + 1].token !== '.') { if (tokens[i + 1].token !== '.') {
parsingContext.addError(`Expected "." to separate field path, got "${tokens[i + 1].token}" in ${context(i)}`); searchContext.addError(`Expected "." to separate field path, got "${tokens[i + 1].token}" in ${context(i)}`);
return; return;
} }
@ -180,13 +180,13 @@ function getExpression(tokens, parsingContext, level = 0) {
if (tokens[i].token === 'text') { if (tokens[i].token === 'text') {
if (tokens[i + 1].token !== '*=*') { if (tokens[i + 1].token !== '*=*') {
parsingContext.addError(`Virtual attribute "note.text" supports only *=* operator, instead given "${tokens[i + 1].token}" in ${context(i)}`); searchContext.addError(`Virtual attribute "note.text" supports only *=* operator, instead given "${tokens[i + 1].token}" in ${context(i)}`);
return; return;
} }
i += 2; i += 2;
return getFulltext([tokens[i]], parsingContext); return getFulltext([tokens[i]], searchContext);
} }
if (PropertyComparisonExp.isProperty(tokens[i].token)) { if (PropertyComparisonExp.isProperty(tokens[i].token)) {
@ -196,7 +196,7 @@ function getExpression(tokens, parsingContext, level = 0) {
const comparator = buildComparator(operator, comparedValue); const comparator = buildComparator(operator, comparedValue);
if (!comparator) { if (!comparator) {
parsingContext.addError(`Can't find operator '${operator}' in ${context(i)}`); searchContext.addError(`Can't find operator '${operator}' in ${context(i)}`);
return; return;
} }
@ -205,7 +205,7 @@ function getExpression(tokens, parsingContext, level = 0) {
return new PropertyComparisonExp(propertyName, comparator); return new PropertyComparisonExp(propertyName, comparator);
} }
parsingContext.addError(`Unrecognized note property "${tokens[i].token}" in ${context(i)}`); searchContext.addError(`Unrecognized note property "${tokens[i].token}" in ${context(i)}`);
} }
function parseAttribute(name) { function parseAttribute(name) {
@ -225,7 +225,7 @@ function getExpression(tokens, parsingContext, level = 0) {
} }
function parseLabel(labelName) { function parseLabel(labelName) {
parsingContext.highlightedTokens.push(labelName); searchContext.highlightedTokens.push(labelName);
if (i < tokens.length - 2 && isOperator(tokens[i + 1].token)) { if (i < tokens.length - 2 && isOperator(tokens[i + 1].token)) {
let operator = tokens[i + 1].token; let operator = tokens[i + 1].token;
@ -238,33 +238,33 @@ function getExpression(tokens, parsingContext, level = 0) {
return; return;
} }
parsingContext.highlightedTokens.push(comparedValue); searchContext.highlightedTokens.push(comparedValue);
if (parsingContext.fuzzyAttributeSearch && operator === '=') { if (searchContext.fuzzyAttributeSearch && operator === '=') {
operator = '*=*'; operator = '*=*';
} }
const comparator = buildComparator(operator, comparedValue); const comparator = buildComparator(operator, comparedValue);
if (!comparator) { if (!comparator) {
parsingContext.addError(`Can't find operator '${operator}' in ${context(i - 1)}`); searchContext.addError(`Can't find operator '${operator}' in ${context(i - 1)}`);
} else { } else {
return new LabelComparisonExp('label', labelName, comparator); return new LabelComparisonExp('label', labelName, comparator);
} }
} else { } else {
return new AttributeExistsExp('label', labelName, parsingContext.fuzzyAttributeSearch); return new AttributeExistsExp('label', labelName, searchContext.fuzzyAttributeSearch);
} }
} }
function parseRelation(relationName) { function parseRelation(relationName) {
parsingContext.highlightedTokens.push(relationName); searchContext.highlightedTokens.push(relationName);
if (i < tokens.length - 2 && tokens[i + 1].token === '.') { if (i < tokens.length - 2 && tokens[i + 1].token === '.') {
i += 1; i += 1;
return new RelationWhereExp(relationName, parseNoteProperty()); return new RelationWhereExp(relationName, parseNoteProperty());
} else { } else {
return new AttributeExistsExp('relation', relationName, parsingContext.fuzzyAttributeSearch); return new AttributeExistsExp('relation', relationName, searchContext.fuzzyAttributeSearch);
} }
} }
@ -293,7 +293,7 @@ function getExpression(tokens, parsingContext, level = 0) {
const valueExtractor = new ValueExtractor(propertyPath); const valueExtractor = new ValueExtractor(propertyPath);
if (valueExtractor.validate()) { if (valueExtractor.validate()) {
parsingContext.addError(valueExtractor.validate()); searchContext.addError(valueExtractor.validate());
} }
orderDefinitions.push({ orderDefinitions.push({
@ -321,7 +321,7 @@ function getExpression(tokens, parsingContext, level = 0) {
for (i = 0; i < tokens.length; i++) { for (i = 0; i < tokens.length; i++) {
if (Array.isArray(tokens[i])) { if (Array.isArray(tokens[i])) {
expressions.push(getExpression(tokens[i], parsingContext, level++)); expressions.push(getExpression(tokens[i], searchContext, level++));
continue; continue;
} }
@ -336,7 +336,7 @@ function getExpression(tokens, parsingContext, level = 0) {
} }
else if (['orderby', 'limit'].includes(token)) { else if (['orderby', 'limit'].includes(token)) {
if (level !== 0) { if (level !== 0) {
parsingContext.addError('orderBy can appear only on the top expression level'); searchContext.addError('orderBy can appear only on the top expression level');
continue; continue;
} }
@ -354,11 +354,11 @@ function getExpression(tokens, parsingContext, level = 0) {
i += 1; i += 1;
if (!Array.isArray(tokens[i])) { if (!Array.isArray(tokens[i])) {
parsingContext.addError(`not keyword should be followed by sub-expression in parenthesis, got ${tokens[i].token} instead`); searchContext.addError(`not keyword should be followed by sub-expression in parenthesis, got ${tokens[i].token} instead`);
continue; continue;
} }
expressions.push(new NotExp(getExpression(tokens[i], parsingContext, level++))); expressions.push(new NotExp(getExpression(tokens[i], searchContext, level++)));
} }
else if (token === 'note') { else if (token === 'note') {
i++; i++;
@ -372,14 +372,14 @@ function getExpression(tokens, parsingContext, level = 0) {
op = token; op = token;
} }
else if (op !== token) { else if (op !== token) {
parsingContext.addError('Mixed usage of AND/OR - always use parenthesis to group AND/OR expressions.'); searchContext.addError('Mixed usage of AND/OR - always use parenthesis to group AND/OR expressions.');
} }
} }
else if (isOperator(token)) { else if (isOperator(token)) {
parsingContext.addError(`Misplaced or incomplete expression "${token}"`); searchContext.addError(`Misplaced or incomplete expression "${token}"`);
} }
else { else {
parsingContext.addError(`Unrecognized expression "${token}"`); searchContext.addError(`Unrecognized expression "${token}"`);
} }
if (!op && expressions.length > 1) { if (!op && expressions.length > 1) {
@ -390,11 +390,11 @@ function getExpression(tokens, parsingContext, level = 0) {
return getAggregateExpression(); return getAggregateExpression();
} }
function parse({fulltextTokens, expressionTokens, parsingContext}) { function parse({fulltextTokens, expressionTokens, searchContext}) {
return AndExp.of([ return AndExp.of([
parsingContext.excludeArchived ? new PropertyComparisonExp("isarchived", buildComparator("=", "false")) : null, searchContext.excludeArchived ? new PropertyComparisonExp("isarchived", buildComparator("=", "false")) : null,
getFulltext(fulltextTokens, parsingContext), getFulltext(fulltextTokens, searchContext),
getExpression(expressionTokens, parsingContext) getExpression(expressionTokens, searchContext)
]); ]);
} }

View File

@ -5,7 +5,7 @@ const handleParens = require('./handle_parens.js');
const parse = require('./parse.js'); const parse = require('./parse.js');
const NoteSet = require("../note_set.js"); const NoteSet = require("../note_set.js");
const SearchResult = require("../search_result.js"); const SearchResult = require("../search_result.js");
const ParsingContext = require("../parsing_context.js"); const SearchContext = require("../search_context.js");
const noteCache = require('../../note_cache/note_cache.js'); const noteCache = require('../../note_cache/note_cache.js');
const noteCacheService = require('../../note_cache/note_cache_service.js'); const noteCacheService = require('../../note_cache/note_cache_service.js');
const hoistedNoteService = require('../../hoisted_note.js'); const hoistedNoteService = require('../../hoisted_note.js');
@ -50,14 +50,14 @@ function findNotesWithExpression(expression) {
return searchResults; return searchResults;
} }
function parseQueryToExpression(query, parsingContext) { function parseQueryToExpression(query, searchContext) {
const {fulltextTokens, expressionTokens} = lex(query); const {fulltextTokens, expressionTokens} = lex(query);
const structuredExpressionTokens = handleParens(expressionTokens); const structuredExpressionTokens = handleParens(expressionTokens);
const expression = parse({ const expression = parse({
fulltextTokens, fulltextTokens,
expressionTokens: structuredExpressionTokens, expressionTokens: structuredExpressionTokens,
parsingContext, searchContext,
originalQuery: query originalQuery: query
}); });
@ -66,16 +66,16 @@ function parseQueryToExpression(query, parsingContext) {
/** /**
* @param {string} query * @param {string} query
* @param {ParsingContext} parsingContext * @param {SearchContext} searchContext
* @return {SearchResult[]} * @return {SearchResult[]}
*/ */
function findNotesWithQuery(query, parsingContext) { function findNotesWithQuery(query, searchContext) {
if (!query.trim().length) { if (!query.trim().length) {
return []; return [];
} }
return utils.stopWatch(`Search with query "${query}"`, () => { return utils.stopWatch(`Search with query "${query}"`, () => {
const expression = parseQueryToExpression(query, parsingContext); const expression = parseQueryToExpression(query, searchContext);
if (!expression) { if (!expression) {
return []; return [];
@ -85,8 +85,8 @@ function findNotesWithQuery(query, parsingContext) {
}, 20); }, 20);
} }
function searchTrimmedNotes(query, parsingContext) { function searchTrimmedNotes(query, searchContext) {
const allSearchResults = findNotesWithQuery(query, parsingContext); const allSearchResults = findNotesWithQuery(query, searchContext);
const trimmedSearchResults = allSearchResults.slice(0, 200); const trimmedSearchResults = allSearchResults.slice(0, 200);
return { return {
@ -96,15 +96,15 @@ function searchTrimmedNotes(query, parsingContext) {
} }
function searchNotesForAutocomplete(query) { function searchNotesForAutocomplete(query) {
const parsingContext = new ParsingContext({ const searchContext = new SearchContext({
includeNoteContent: false, includeNoteContent: false,
excludeArchived: true, excludeArchived: true,
fuzzyAttributeSearch: true fuzzyAttributeSearch: true
}); });
const {results} = searchTrimmedNotes(query, parsingContext); const {results} = searchTrimmedNotes(query, searchContext);
highlightSearchResults(results, parsingContext.highlightedTokens); highlightSearchResults(results, searchContext.highlightedTokens);
return results.map(result => { return results.map(result => {
return { return {