mirror of
				https://github.com/zadam/trilium.git
				synced 2025-10-31 18:36:30 +01:00 
			
		
		
		
	sorting search results occurences in the note title
This commit is contained in:
		
							
								
								
									
										6
									
								
								package-lock.json
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										6
									
								
								package-lock.json
									
									
									
										generated
									
									
									
								
							| @@ -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", | ||||
|   | ||||
| @@ -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", | ||||
|   | ||||
| @@ -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; | ||||
|   | ||||
| @@ -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(); | ||||
|  | ||||
|   | ||||
| @@ -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(); | ||||
|  | ||||
|   | ||||
| @@ -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; | ||||
|   | ||||
| @@ -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); | ||||
|     } | ||||
|   | ||||
| @@ -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]); | ||||
|                 } | ||||
|   | ||||
| @@ -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; | ||||
|   | ||||
| @@ -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) { | ||||
|   | ||||
| @@ -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(); | ||||
|  | ||||
|   | ||||
| @@ -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) { | ||||
|   | ||||
| @@ -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) { | ||||
|   | ||||
| @@ -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) { | ||||
|   | ||||
| @@ -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; | ||||
|   | ||||
| @@ -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); | ||||
| } | ||||
|  | ||||
|   | ||||
		Reference in New Issue
	
	Block a user