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');
function tokens(toks, cur = 0) {
@ -24,7 +24,7 @@ describe("Parser", () => {
const rootExp = parse({
fulltextTokens: tokens(["hello", "hi"]),
expressionTokens: [],
parsingContext: new ParsingContext({includeNoteContent: false})
searchContext: new SearchContext({includeNoteContent: false})
});
expect(rootExp.constructor.name).toEqual("AndExp");
@ -36,7 +36,7 @@ describe("Parser", () => {
const rootExp = parse({
fulltextTokens: tokens(["hello", "hi"]),
expressionTokens: [],
parsingContext: new ParsingContext({includeNoteContent: true})
searchContext: new SearchContext({includeNoteContent: true})
});
expect(rootExp.constructor.name).toEqual("AndExp");
@ -59,7 +59,7 @@ describe("Parser", () => {
const rootExp = parse({
fulltextTokens: [],
expressionTokens: tokens(["#mylabel", "=", "text"]),
parsingContext: new ParsingContext()
searchContext: new SearchContext()
});
expect(rootExp.constructor.name).toEqual("LabelComparisonExp");
@ -72,7 +72,7 @@ describe("Parser", () => {
let rootExp = parse({
fulltextTokens: [],
expressionTokens: tokens(["#!mylabel"]),
parsingContext: new ParsingContext()
searchContext: new SearchContext()
});
expect(rootExp.constructor.name).toEqual("NotExp");
@ -83,7 +83,7 @@ describe("Parser", () => {
rootExp = parse({
fulltextTokens: [],
expressionTokens: tokens(["~!myrelation"]),
parsingContext: new ParsingContext()
searchContext: new SearchContext()
});
expect(rootExp.constructor.name).toEqual("NotExp");
@ -96,7 +96,7 @@ describe("Parser", () => {
const rootExp = parse({
fulltextTokens: [],
expressionTokens: tokens(["#first", "=", "text", "and", "#second", "=", "text"]),
parsingContext: new ParsingContext(true)
searchContext: new SearchContext(true)
});
expect(rootExp.constructor.name).toEqual("AndExp");
@ -113,7 +113,7 @@ describe("Parser", () => {
const rootExp = parse({
fulltextTokens: [],
expressionTokens: tokens(["#first", "=", "text", "#second", "=", "text"]),
parsingContext: new ParsingContext()
searchContext: new SearchContext()
});
expect(rootExp.constructor.name).toEqual("AndExp");
@ -130,7 +130,7 @@ describe("Parser", () => {
const rootExp = parse({
fulltextTokens: [],
expressionTokens: tokens(["#first", "=", "text", "or", "#second", "=", "text"]),
parsingContext: new ParsingContext()
searchContext: new SearchContext()
});
expect(rootExp.constructor.name).toEqual("OrExp");
@ -147,7 +147,7 @@ describe("Parser", () => {
const rootExp = parse({
fulltextTokens: tokens(["hello"]),
expressionTokens: tokens(["#mylabel", "=", "text"]),
parsingContext: new ParsingContext()
searchContext: new SearchContext()
});
expect(rootExp.constructor.name).toEqual("AndExp");
@ -165,7 +165,7 @@ describe("Parser", () => {
const rootExp = parse({
fulltextTokens: [],
expressionTokens: tokens(["#first", "=", "text", "or", ["#second", "=", "text", "and", "#third", "=", "text"]]),
parsingContext: new ParsingContext()
searchContext: new SearchContext()
});
expect(rootExp.constructor.name).toEqual("OrExp");
@ -187,39 +187,39 @@ describe("Parser", () => {
describe("Invalid expressions", () => {
it("incomplete comparison", () => {
const parsingContext = new ParsingContext();
const searchContext = new SearchContext();
parse({
fulltextTokens: [],
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", () => {
let parsingContext = new ParsingContext();
parsingContext.originalQuery = "#first = #second";
let searchContext = new SearchContext();
searchContext.originalQuery = "#first = #second";
parse({
fulltextTokens: [],
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();
parsingContext.originalQuery = "#first = note.relations.second";
searchContext = new SearchContext();
searchContext.originalQuery = "#first = note.relations.second";
parse({
fulltextTokens: [],
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({
fulltextTokens: [],
@ -228,7 +228,7 @@ describe("Invalid expressions", () => {
{ token: "=", inQuotes: false },
{ token: "#second", inQuotes: true },
],
parsingContext: new ParsingContext()
searchContext: new SearchContext()
});
expect(rootExp.constructor.name).toEqual("LabelComparisonExp");

View file

@ -1,7 +1,7 @@
const searchService = require('../../src/services/search/services/search.js');
const Note = require('../../src/services/note_cache/entities/note.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 noteCache = require('../../src/services/note_cache/note_cache.js');
const {NoteBuilder, findNoteByTitle, note} = require('./note_cache_mocking.js');
@ -22,8 +22,8 @@ describe("Search", () => {
.child(note("Austria"))
);
const parsingContext = new ParsingContext();
const searchResults = searchService.findNotesWithQuery('europe austria', parsingContext);
const searchContext = new SearchContext();
const searchResults = searchService.findNotesWithQuery('europe austria', searchContext);
expect(searchResults.length).toEqual(1);
expect(findNoteByTitle(searchResults, "Austria")).toBeTruthy();
@ -39,13 +39,13 @@ describe("Search", () => {
.child(vienna
.label('inhabitants', '1888776'));
const parsingContext = new ParsingContext();
let searchResults = searchService.findNotesWithQuery('capital', parsingContext);
const searchContext = new SearchContext();
let searchResults = searchService.findNotesWithQuery('capital', searchContext);
expect(searchResults.length).toEqual(1);
expect(findNoteByTitle(searchResults, "Austria")).toBeTruthy();
searchResults = searchService.findNotesWithQuery('inhabitants', parsingContext);
searchResults = searchService.findNotesWithQuery('inhabitants', searchContext);
expect(searchResults.length).toEqual(1);
expect(findNoteByTitle(searchResults, "Vienna")).toBeTruthy();
@ -56,18 +56,18 @@ describe("Search", () => {
.child(note("Effective Java", 'book', ''))
.child(note("Hello World.java", 'code', 'text/x-java'));
const parsingContext = new ParsingContext();
let searchResults = searchService.findNotesWithQuery('book', parsingContext);
const searchContext = new SearchContext();
let searchResults = searchService.findNotesWithQuery('book', searchContext);
expect(searchResults.length).toEqual(1);
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(findNoteByTitle(searchResults, "Hello World.java")).toBeTruthy();
searchResults = searchService.findNotesWithQuery('java', parsingContext);
searchResults = searchService.findNotesWithQuery('java', searchContext);
expect(searchResults.length).toEqual(2);
});
@ -78,8 +78,8 @@ describe("Search", () => {
.child(note("Austria"))
);
const parsingContext = new ParsingContext();
const searchResults = searchService.findNotesWithQuery('europe', parsingContext);
const searchContext = new SearchContext();
const searchResults = searchService.findNotesWithQuery('europe', searchContext);
expect(searchResults.length).toEqual(1);
expect(findNoteByTitle(searchResults, "Europe")).toBeTruthy();
@ -92,9 +92,9 @@ describe("Search", () => {
.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(findNoteByTitle(searchResults, "Austria")).toBeTruthy();
});
@ -108,9 +108,9 @@ describe("Search", () => {
.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(findNoteByTitle(searchResults, "Austria")).toBeTruthy();
});
@ -124,9 +124,9 @@ describe("Search", () => {
.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(findNoteByTitle(searchResults, "Czech Republic")).toBeTruthy();
});
@ -141,9 +141,9 @@ describe("Search", () => {
.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(findNoteByTitle(searchResults, "Czech Republic")).toBeTruthy();
});
@ -162,13 +162,13 @@ describe("Search", () => {
.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(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(findNoteByTitle(searchResults, "Austria")).toBeTruthy();
expect(findNoteByTitle(searchResults, "Czech Republic")).toBeTruthy();
@ -185,10 +185,10 @@ describe("Search", () => {
.label('dateTime', dateUtils.localNowDateTime())
);
const parsingContext = new ParsingContext();
const searchContext = new SearchContext();
function test(query, expectedResultCount) {
const searchResults = searchService.findNotesWithQuery(query, parsingContext);
const searchResults = searchService.findNotesWithQuery(query, searchContext);
expect(searchResults.length).toEqual(expectedResultCount);
if (expectedResultCount === 1) {
@ -238,9 +238,9 @@ describe("Search", () => {
.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(findNoteByTitle(searchResults, "Czech Republic")).toBeTruthy();
expect(findNoteByTitle(searchResults, "Austria")).toBeTruthy();
@ -255,20 +255,20 @@ describe("Search", () => {
.child(note("Czech Republic")
.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);
searchResults = searchService.findNotesWithQuery('#languageFamily=ger', parsingContext);
searchResults = searchService.findNotesWithQuery('#languageFamily=ger', searchContext);
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);
searchResults = searchService.findNotesWithQuery('#languageFamily=ger', parsingContext);
searchResults = searchService.findNotesWithQuery('#languageFamily=ger', searchContext);
expect(searchResults.length).toEqual(1);
expect(findNoteByTitle(searchResults, "Austria")).toBeTruthy();
});
@ -279,9 +279,9 @@ describe("Search", () => {
.child(note("Austria"))
.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(findNoteByTitle(searchResults, "Czech Republic")).toBeTruthy();
});
@ -296,18 +296,18 @@ describe("Search", () => {
.child(note("Asia")
.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(findNoteByTitle(searchResults, "Austria")).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(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(findNoteByTitle(searchResults, "Prague")).toBeTruthy();
});
@ -324,13 +324,13 @@ describe("Search", () => {
.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(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(findNoteByTitle(searchResults, "Taipei")).toBeTruthy();
});
@ -345,18 +345,18 @@ describe("Search", () => {
.child(note("Oceania")
.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(findNoteByTitle(searchResults, "Europe")).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(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(findNoteByTitle(searchResults, "Europe")).toBeTruthy();
});
@ -375,13 +375,13 @@ describe("Search", () => {
.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(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(findNoteByTitle(searchResults, "Spain")).toBeTruthy();
});
@ -400,9 +400,9 @@ describe("Search", () => {
.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(findNoteByTitle(searchResults, "Czech Republic")).toBeTruthy();
});
@ -426,13 +426,13 @@ describe("Search", () => {
.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(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(findNoteByTitle(searchResults, "Czech Republic")).toBeTruthy();
expect(findNoteByTitle(searchResults, "Austria")).toBeTruthy();
@ -463,10 +463,10 @@ describe("Search", () => {
austria.note.utcDateModified = '2020-05-14 11:11:42.001Z';
austria.note.contentLength = 1001;
const parsingContext = new ParsingContext();
const searchContext = new SearchContext();
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);
}
@ -520,38 +520,38 @@ describe("Search", () => {
.child(austria)
.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(noteCache.notes[searchResults[0].noteId].title).toEqual("Austria");
expect(noteCache.notes[searchResults[1].noteId].title).toEqual("Italy");
expect(noteCache.notes[searchResults[2].noteId].title).toEqual("Slovakia");
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(noteCache.notes[searchResults[0].noteId].title).toEqual("Slovakia");
expect(noteCache.notes[searchResults[1].noteId].title).toEqual("Ukraine");
expect(noteCache.notes[searchResults[2].noteId].title).toEqual("Italy");
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(noteCache.notes[searchResults[0].noteId].title).toEqual("Austria");
expect(noteCache.notes[searchResults[1].noteId].title).toEqual("Italy");
expect(noteCache.notes[searchResults[2].noteId].title).toEqual("Ukraine");
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(noteCache.notes[searchResults[0].noteId].title).toEqual("Austria");
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);
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);
});
@ -564,13 +564,13 @@ describe("Search", () => {
.child(slovakia)
.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(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(noteCache.notes[searchResults[0].noteId].title).toEqual("Europe");
});
@ -584,9 +584,9 @@ describe("Search", () => {
.child(slovakia)
.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(noteCache.notes[searchResults[0].noteId].title).toEqual("Slovakia");
});
@ -601,9 +601,9 @@ describe("Search", () => {
.child(note('Post Y')))
.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(noteCache.notes[searchResults[0].noteId].title).toEqual("Reddit is bad");
});
@ -624,9 +624,9 @@ describe("Search", () => {
// .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(findNoteByTitle(searchResults, "Czech Republic")).toBeTruthy();
// expect(findNoteByTitle(searchResults, "Austria")).toBeTruthy();

View file

@ -1,19 +1,19 @@
"use strict";
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 scriptService = require('../../services/script');
const searchService = require('../../services/search/services/search');
function searchNotes(req) {
const parsingContext = new ParsingContext({
const searchContext = new SearchContext({
includeNoteContent: req.query.includeNoteContent === 'true',
excludeArchived: req.query.excludeArchived === '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 {
return {

View file

@ -12,7 +12,7 @@ const dayjs = require('dayjs');
const cloningService = require('./cloning');
const appInfo = require('./app_info');
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.
@ -92,13 +92,13 @@ function BackendScriptApi(currentNote, apiParams) {
*
* @method
* @param {string} query
* @param {ParsingContext} [parsingContext]
* @param {SearchContext} [searchContext]
* @returns {Note[]}
*/
this.searchForNotes = (query, parsingContext) => {
parsingContext = parsingContext || new ParsingContext();
this.searchForNotes = (query, searchContext) => {
searchContext = searchContext || new SearchContext();
const noteIds = searchService.findNotesWithQuery(query, parsingContext)
const noteIds = searchService.findNotesWithQuery(query, searchContext)
.map(sr => sr.noteId);
return repository.getNotes(noteIds);

View file

@ -1,6 +1,6 @@
"use strict";
class ParsingContext {
class SearchContext {
constructor(params = {}) {
this.includeNoteContent = !!params.includeNoteContent;
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 ValueExtractor = require('../value_extractor.js');
function getFulltext(tokens, parsingContext) {
function getFulltext(tokens, searchContext) {
tokens = tokens.map(t => t.token);
parsingContext.highlightedTokens.push(...tokens);
searchContext.highlightedTokens.push(...tokens);
if (tokens.length === 0) {
return null;
}
if (parsingContext.includeNoteContent) {
if (searchContext.includeNoteContent) {
return new OrExp([
new NoteCacheFulltextExp(tokens),
new NoteContentProtectedFulltextExp('*=*', tokens),
@ -43,7 +43,7 @@ function isOperator(str) {
return str.match(/^[=<>*]+$/);
}
function getExpression(tokens, parsingContext, level = 0) {
function getExpression(tokens, searchContext, level = 0) {
if (tokens.length === 0) {
return null;
}
@ -56,11 +56,11 @@ function getExpression(tokens, parsingContext, level = 0) {
function context(i) {
let {startIndex, endIndex} = tokens[i];
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 ? "..." : "")
+ parsingContext.originalQuery.substr(startIndex, endIndex - startIndex)
+ (endIndex !== parsingContext.originalQuery.length ? "..." : "") + '"';
+ searchContext.originalQuery.substr(startIndex, endIndex - startIndex)
+ (endIndex !== searchContext.originalQuery.length ? "..." : "") + '"';
}
function resolveConstantOperand() {
@ -68,7 +68,7 @@ function getExpression(tokens, parsingContext, level = 0) {
if (!operand.inQuotes
&& (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;
}
@ -114,7 +114,7 @@ function getExpression(tokens, parsingContext, level = 0) {
function parseNoteProperty() {
if (tokens[i].token !== '.') {
parsingContext.addError('Expected "." to separate field path');
searchContext.addError('Expected "." to separate field path');
return;
}
@ -126,7 +126,7 @@ function getExpression(tokens, parsingContext, level = 0) {
const operator = tokens[i].token;
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;
}
@ -158,7 +158,7 @@ function getExpression(tokens, parsingContext, level = 0) {
if (tokens[i].token === 'labels') {
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;
}
@ -169,7 +169,7 @@ function getExpression(tokens, parsingContext, level = 0) {
if (tokens[i].token === 'relations') {
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;
}
@ -180,13 +180,13 @@ function getExpression(tokens, parsingContext, level = 0) {
if (tokens[i].token === 'text') {
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;
}
i += 2;
return getFulltext([tokens[i]], parsingContext);
return getFulltext([tokens[i]], searchContext);
}
if (PropertyComparisonExp.isProperty(tokens[i].token)) {
@ -196,7 +196,7 @@ function getExpression(tokens, parsingContext, level = 0) {
const comparator = buildComparator(operator, comparedValue);
if (!comparator) {
parsingContext.addError(`Can't find operator '${operator}' in ${context(i)}`);
searchContext.addError(`Can't find operator '${operator}' in ${context(i)}`);
return;
}
@ -205,7 +205,7 @@ function getExpression(tokens, parsingContext, level = 0) {
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) {
@ -225,7 +225,7 @@ function getExpression(tokens, parsingContext, level = 0) {
}
function parseLabel(labelName) {
parsingContext.highlightedTokens.push(labelName);
searchContext.highlightedTokens.push(labelName);
if (i < tokens.length - 2 && isOperator(tokens[i + 1].token)) {
let operator = tokens[i + 1].token;
@ -238,33 +238,33 @@ function getExpression(tokens, parsingContext, level = 0) {
return;
}
parsingContext.highlightedTokens.push(comparedValue);
searchContext.highlightedTokens.push(comparedValue);
if (parsingContext.fuzzyAttributeSearch && operator === '=') {
if (searchContext.fuzzyAttributeSearch && operator === '=') {
operator = '*=*';
}
const comparator = buildComparator(operator, comparedValue);
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 {
return new LabelComparisonExp('label', labelName, comparator);
}
} else {
return new AttributeExistsExp('label', labelName, parsingContext.fuzzyAttributeSearch);
return new AttributeExistsExp('label', labelName, searchContext.fuzzyAttributeSearch);
}
}
function parseRelation(relationName) {
parsingContext.highlightedTokens.push(relationName);
searchContext.highlightedTokens.push(relationName);
if (i < tokens.length - 2 && tokens[i + 1].token === '.') {
i += 1;
return new RelationWhereExp(relationName, parseNoteProperty());
} 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);
if (valueExtractor.validate()) {
parsingContext.addError(valueExtractor.validate());
searchContext.addError(valueExtractor.validate());
}
orderDefinitions.push({
@ -321,7 +321,7 @@ function getExpression(tokens, parsingContext, level = 0) {
for (i = 0; i < tokens.length; i++) {
if (Array.isArray(tokens[i])) {
expressions.push(getExpression(tokens[i], parsingContext, level++));
expressions.push(getExpression(tokens[i], searchContext, level++));
continue;
}
@ -336,7 +336,7 @@ function getExpression(tokens, parsingContext, level = 0) {
}
else if (['orderby', 'limit'].includes(token)) {
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;
}
@ -354,11 +354,11 @@ function getExpression(tokens, parsingContext, level = 0) {
i += 1;
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;
}
expressions.push(new NotExp(getExpression(tokens[i], parsingContext, level++)));
expressions.push(new NotExp(getExpression(tokens[i], searchContext, level++)));
}
else if (token === 'note') {
i++;
@ -372,14 +372,14 @@ function getExpression(tokens, parsingContext, level = 0) {
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)) {
parsingContext.addError(`Misplaced or incomplete expression "${token}"`);
searchContext.addError(`Misplaced or incomplete expression "${token}"`);
}
else {
parsingContext.addError(`Unrecognized expression "${token}"`);
searchContext.addError(`Unrecognized expression "${token}"`);
}
if (!op && expressions.length > 1) {
@ -390,11 +390,11 @@ function getExpression(tokens, parsingContext, level = 0) {
return getAggregateExpression();
}
function parse({fulltextTokens, expressionTokens, parsingContext}) {
function parse({fulltextTokens, expressionTokens, searchContext}) {
return AndExp.of([
parsingContext.excludeArchived ? new PropertyComparisonExp("isarchived", buildComparator("=", "false")) : null,
getFulltext(fulltextTokens, parsingContext),
getExpression(expressionTokens, parsingContext)
searchContext.excludeArchived ? new PropertyComparisonExp("isarchived", buildComparator("=", "false")) : null,
getFulltext(fulltextTokens, searchContext),
getExpression(expressionTokens, searchContext)
]);
}

View file

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