From be543737a98a5b41645af1f76cfe749a60c13d58 Mon Sep 17 00:00:00 2001 From: zadam Date: Fri, 11 Dec 2020 13:54:41 +0100 Subject: [PATCH] sorting search results occurences in the note title --- package-lock.json | 6 ++--- package.json | 2 +- src/services/search/expressions/and.js | 4 +-- src/services/search/expressions/child_of.js | 4 +-- .../search/expressions/descendant_of.js | 4 +-- src/services/search/expressions/expression.js | 4 +-- src/services/search/expressions/not.js | 4 +-- .../expressions/note_cache_flat_text.js | 4 +-- src/services/search/expressions/or.js | 4 +-- .../search/expressions/order_by_and_limit.js | 4 +-- src/services/search/expressions/parent_of.js | 4 +-- .../search/expressions/property_comparison.js | 2 +- .../search/expressions/relation_where.js | 4 +-- src/services/search/expressions/sub_tree.js | 2 +- src/services/search/search_result.js | 20 ++++++++++++++ src/services/search/services/search.js | 27 ++++++++++++++----- 16 files changed, 66 insertions(+), 33 deletions(-) diff --git a/package-lock.json b/package-lock.json index 5ecad559a..f51c1c5d4 100644 --- a/package-lock.json +++ b/package-lock.json @@ -4325,9 +4325,9 @@ "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" }, "ini": { - "version": "1.3.5", - "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.5.tgz", - "integrity": "sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw==" + "version": "1.3.7", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.7.tgz", + "integrity": "sha512-iKpRpXP+CrP2jyrxvg1kMUpXDyRUFDWurxbnVT1vQPx+Wz9uCYsMIqYuSBLV+PAaZG/d7kRLKRFc9oDMsH+mFQ==" }, "interpret": { "version": "2.2.0", diff --git a/package.json b/package.json index b9b5397f7..1a3ff340a 100644 --- a/package.json +++ b/package.json @@ -47,7 +47,7 @@ "http-proxy-agent": "4.0.1", "https-proxy-agent": "5.0.0", "image-type": "4.1.0", - "ini": "1.3.5", + "ini": "1.3.7", "is-svg": "4.2.1", "jimp": "0.16.1", "jsdom": "^16.4.0", diff --git a/src/services/search/expressions/and.js b/src/services/search/expressions/and.js index ee22f6b13..4ac216939 100644 --- a/src/services/search/expressions/and.js +++ b/src/services/search/expressions/and.js @@ -18,9 +18,9 @@ class AndExp extends Expression { this.subExpressions = subExpressions; } - execute(inputNoteSet, searchContext) { + execute(inputNoteSet, executionContext) { for (const subExpression of this.subExpressions) { - inputNoteSet = subExpression.execute(inputNoteSet, searchContext); + inputNoteSet = subExpression.execute(inputNoteSet, executionContext); } return inputNoteSet; diff --git a/src/services/search/expressions/child_of.js b/src/services/search/expressions/child_of.js index a98b0030c..87085f120 100644 --- a/src/services/search/expressions/child_of.js +++ b/src/services/search/expressions/child_of.js @@ -10,14 +10,14 @@ class ChildOfExp extends Expression { this.subExpression = subExpression; } - execute(inputNoteSet, searchContext) { + execute(inputNoteSet, executionContext) { const subInputNoteSet = new NoteSet(); for (const note of inputNoteSet.notes) { subInputNoteSet.addAll(note.parents); } - const subResNoteSet = this.subExpression.execute(subInputNoteSet, searchContext); + const subResNoteSet = this.subExpression.execute(subInputNoteSet, executionContext); const resNoteSet = new NoteSet(); diff --git a/src/services/search/expressions/descendant_of.js b/src/services/search/expressions/descendant_of.js index 51e01748a..f6ad97ce4 100644 --- a/src/services/search/expressions/descendant_of.js +++ b/src/services/search/expressions/descendant_of.js @@ -11,9 +11,9 @@ class DescendantOfExp extends Expression { this.subExpression = subExpression; } - execute(inputNoteSet, searchContext) { + execute(inputNoteSet, executionContext) { const subInputNoteSet = new NoteSet(Object.values(noteCache.notes)); - const subResNoteSet = this.subExpression.execute(subInputNoteSet, searchContext); + const subResNoteSet = this.subExpression.execute(subInputNoteSet, executionContext); const subTreeNoteSet = new NoteSet(); diff --git a/src/services/search/expressions/expression.js b/src/services/search/expressions/expression.js index 41192cbb4..12837ccb6 100644 --- a/src/services/search/expressions/expression.js +++ b/src/services/search/expressions/expression.js @@ -3,10 +3,10 @@ class Expression { /** * @param {NoteSet} inputNoteSet - * @param {object} searchContext + * @param {object} executionContext * @return {NoteSet} */ - execute(inputNoteSet, searchContext) {} + execute(inputNoteSet, executionContext) {} } module.exports = Expression; diff --git a/src/services/search/expressions/not.js b/src/services/search/expressions/not.js index a24d3c2c1..43986504a 100644 --- a/src/services/search/expressions/not.js +++ b/src/services/search/expressions/not.js @@ -9,8 +9,8 @@ class NotExp extends Expression { this.subExpression = subExpression; } - execute(inputNoteSet, searchContext) { - const subNoteSet = this.subExpression.execute(inputNoteSet, searchContext); + execute(inputNoteSet, executionContext) { + const subNoteSet = this.subExpression.execute(inputNoteSet, executionContext); return inputNoteSet.minus(subNoteSet); } diff --git a/src/services/search/expressions/note_cache_flat_text.js b/src/services/search/expressions/note_cache_flat_text.js index bbb5cbcea..ce25836c1 100644 --- a/src/services/search/expressions/note_cache_flat_text.js +++ b/src/services/search/expressions/note_cache_flat_text.js @@ -11,7 +11,7 @@ class NoteCacheFlatTextExp extends Expression { this.tokens = tokens; } - execute(inputNoteSet, searchContext) { + execute(inputNoteSet, executionContext) { // has deps on SQL which breaks unit test so needs to be dynamically required const noteCacheService = require('../../note_cache/note_cache_service'); const resultNoteSet = new NoteSet(); @@ -22,7 +22,7 @@ class NoteCacheFlatTextExp extends Expression { if (retPath) { const noteId = retPath[retPath.length - 1]; - searchContext.noteIdToNotePath[noteId] = retPath; + executionContext.noteIdToNotePath[noteId] = retPath; resultNoteSet.add(noteCache.notes[noteId]); } diff --git a/src/services/search/expressions/or.js b/src/services/search/expressions/or.js index 62c16f5cf..d04725670 100644 --- a/src/services/search/expressions/or.js +++ b/src/services/search/expressions/or.js @@ -21,11 +21,11 @@ class OrExp extends Expression { this.subExpressions = subExpressions; } - execute(inputNoteSet, searchContext) { + execute(inputNoteSet, executionContext) { const resultNoteSet = new NoteSet(); for (const subExpression of this.subExpressions) { - resultNoteSet.mergeIn(subExpression.execute(inputNoteSet, searchContext)); + resultNoteSet.mergeIn(subExpression.execute(inputNoteSet, executionContext)); } return resultNoteSet; diff --git a/src/services/search/expressions/order_by_and_limit.js b/src/services/search/expressions/order_by_and_limit.js index 3a91484c5..758e77c38 100644 --- a/src/services/search/expressions/order_by_and_limit.js +++ b/src/services/search/expressions/order_by_and_limit.js @@ -20,8 +20,8 @@ class OrderByAndLimitExp extends Expression { this.subExpression = null; // it's expected to be set after construction } - execute(inputNoteSet, searchContext) { - let {notes} = this.subExpression.execute(inputNoteSet, searchContext); + execute(inputNoteSet, executionContext) { + let {notes} = this.subExpression.execute(inputNoteSet, executionContext); notes.sort((a, b) => { for (const {valueExtractor, smaller, larger} of this.orderDefinitions) { diff --git a/src/services/search/expressions/parent_of.js b/src/services/search/expressions/parent_of.js index e7924feb7..6fb2ebdce 100644 --- a/src/services/search/expressions/parent_of.js +++ b/src/services/search/expressions/parent_of.js @@ -10,14 +10,14 @@ class ParentOfExp extends Expression { this.subExpression = subExpression; } - execute(inputNoteSet, searchContext) { + execute(inputNoteSet, executionContext) { const subInputNoteSet = new NoteSet(); for (const note of inputNoteSet.notes) { subInputNoteSet.addAll(note.children); } - const subResNoteSet = this.subExpression.execute(subInputNoteSet, searchContext); + const subResNoteSet = this.subExpression.execute(subInputNoteSet, executionContext); const resNoteSet = new NoteSet(); diff --git a/src/services/search/expressions/property_comparison.js b/src/services/search/expressions/property_comparison.js index 6ee7ce63e..809247724 100644 --- a/src/services/search/expressions/property_comparison.js +++ b/src/services/search/expressions/property_comparison.js @@ -37,7 +37,7 @@ class PropertyComparisonExp extends Expression { this.comparator = comparator; } - execute(inputNoteSet, searchContext) { + execute(inputNoteSet, executionContext) { const resNoteSet = new NoteSet(); for (const note of inputNoteSet.notes) { diff --git a/src/services/search/expressions/relation_where.js b/src/services/search/expressions/relation_where.js index f873762e0..486b1b941 100644 --- a/src/services/search/expressions/relation_where.js +++ b/src/services/search/expressions/relation_where.js @@ -12,7 +12,7 @@ class RelationWhereExp extends Expression { this.subExpression = subExpression; } - execute(inputNoteSet, searchContext) { + execute(inputNoteSet, executionContext) { const candidateNoteSet = new NoteSet(); for (const attr of noteCache.findAttributes('relation', this.relationName)) { @@ -20,7 +20,7 @@ class RelationWhereExp extends Expression { if (inputNoteSet.hasNoteId(note.noteId)) { const subInputNoteSet = new NoteSet([attr.targetNote]); - const subResNoteSet = this.subExpression.execute(subInputNoteSet, searchContext); + const subResNoteSet = this.subExpression.execute(subInputNoteSet, executionContext); if (subResNoteSet.hasNote(attr.targetNote)) { if (attr.isInheritable) { diff --git a/src/services/search/expressions/sub_tree.js b/src/services/search/expressions/sub_tree.js index 8c24dd9c1..fc6e58e1f 100644 --- a/src/services/search/expressions/sub_tree.js +++ b/src/services/search/expressions/sub_tree.js @@ -12,7 +12,7 @@ class SubTreeExp extends Expression { this.subTreeNoteId = subTreeNoteId; } - execute(inputNoteSet, searchContext) { + execute(inputNoteSet, executionContext) { const subTreeNote = noteCache.notes[this.subTreeNoteId]; if (!subTreeNote) { diff --git a/src/services/search/search_result.js b/src/services/search/search_result.js index 83c395b10..9d0ea334a 100644 --- a/src/services/search/search_result.js +++ b/src/services/search/search_result.js @@ -15,6 +15,26 @@ class SearchResult { get noteId() { return this.notePathArray[this.notePathArray.length - 1]; } + + computeScore(tokens) { + this.score = 0; + + const chunks = this.notePathTitle.toLowerCase().split(" "); + + for (const chunk of chunks) { + for (const token of tokens) { + if (chunk === token) { + this.score += 4 * token.length; + } + else if (chunk.startsWith(token)) { + this.score += 2 * token.length; + } + else if (chunk.includes(token)) { + this.score += token.length; + } + } + } + } } module.exports = SearchResult; diff --git a/src/services/search/services/search.js b/src/services/search/services/search.js index 733455615..224e55c18 100644 --- a/src/services/search/services/search.js +++ b/src/services/search/services/search.js @@ -13,9 +13,10 @@ const cls = require('../../cls.js'); /** * @param {Expression} expression + * @param {SearchContext} searchContext * @return {SearchResult[]} */ -function findNotesWithExpression(expression) { +function findNotesWithExpression(expression, searchContext) { const hoistedNote = noteCache.notes[cls.getHoistedNoteId()]; let allNotes = (hoistedNote && hoistedNote.noteId !== 'root') ? hoistedNote.subtreeNotes @@ -27,27 +28,39 @@ function findNotesWithExpression(expression) { const allNoteSet = new NoteSet(allNotes); - const searchContext = { + const executionContext = { noteIdToNotePath: {} }; - const noteSet = expression.execute(allNoteSet, searchContext); + const noteSet = expression.execute(allNoteSet, executionContext); const searchResults = noteSet.notes - .map(note => searchContext.noteIdToNotePath[note.noteId] || noteCacheService.getSomePath(note)) + .map(note => executionContext.noteIdToNotePath[note.noteId] || noteCacheService.getSomePath(note)) .filter(notePathArray => notePathArray.includes(cls.getHoistedNoteId())) .map(notePathArray => new SearchResult(notePathArray)); + for (const res of searchResults) { + res.computeScore(searchContext.highlightedTokens); + } + if (!noteSet.sorted) { - // sort results by depth of the note. This is based on the assumption that more important results - // are closer to the note root. searchResults.sort((a, b) => { + if (a.score > b.score) { + return -1; + } else if (a.score < b.score) { + return 1; + } + + // if score does not decide then sort results by depth of the note. + // This is based on the assumption that more important results are closer to the note root. if (a.notePathArray.length === b.notePathArray.length) { return a.notePathTitle < b.notePathTitle ? -1 : 1; } return a.notePathArray.length < b.notePathArray.length ? -1 : 1; }); + + } return searchResults; @@ -86,7 +99,7 @@ function findNotesWithQuery(query, searchContext) { return []; } - return findNotesWithExpression(expression); + return findNotesWithExpression(expression, searchContext); }, 20); }