mirror of
https://github.com/zadam/trilium.git
synced 2025-06-06 01:48:32 +02:00
renamed ParsingContext to SearchContext
This commit is contained in:
parent
0c5f842626
commit
a73733d0fc
@ -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");
|
||||||
|
@ -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();
|
||||||
|
@ -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 {
|
||||||
|
@ -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);
|
||||||
|
@ -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;
|
@ -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)
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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 {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user