mirror of
				https://github.com/TriliumNext/Notes.git
				synced 2025-11-04 15:11:31 +08:00 
			
		
		
		
	full text search uses in-memory search even for unprotected notes and preprocesses content with tag stripping
This commit is contained in:
		
							parent
							
								
									e1d4be814f
								
							
						
					
					
						commit
						0eb77e43e2
					
				
							
								
								
									
										5
									
								
								package-lock.json
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										5
									
								
								package-lock.json
									
									
									
										generated
									
									
									
								
							@ -7346,6 +7346,11 @@
 | 
				
			|||||||
        "escape-string-regexp": "^1.0.2"
 | 
					        "escape-string-regexp": "^1.0.2"
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
 | 
					    "striptags": {
 | 
				
			||||||
 | 
					      "version": "3.1.1",
 | 
				
			||||||
 | 
					      "resolved": "https://registry.npmjs.org/striptags/-/striptags-3.1.1.tgz",
 | 
				
			||||||
 | 
					      "integrity": "sha1-yMPn/db7S7OjKjt1LltePjgJPr0="
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
    "strtok3": {
 | 
					    "strtok3": {
 | 
				
			||||||
      "version": "6.0.3",
 | 
					      "version": "6.0.3",
 | 
				
			||||||
      "resolved": "https://registry.npmjs.org/strtok3/-/strtok3-6.0.3.tgz",
 | 
					      "resolved": "https://registry.npmjs.org/strtok3/-/strtok3-6.0.3.tgz",
 | 
				
			||||||
 | 
				
			|||||||
@ -66,6 +66,7 @@
 | 
				
			|||||||
    "serve-favicon": "2.5.0",
 | 
					    "serve-favicon": "2.5.0",
 | 
				
			||||||
    "session-file-store": "1.4.0",
 | 
					    "session-file-store": "1.4.0",
 | 
				
			||||||
    "string-similarity": "4.0.1",
 | 
					    "string-similarity": "4.0.1",
 | 
				
			||||||
 | 
					    "striptags": "^3.1.1",
 | 
				
			||||||
    "turndown": "6.0.0",
 | 
					    "turndown": "6.0.0",
 | 
				
			||||||
    "turndown-plugin-gfm": "1.0.2",
 | 
					    "turndown-plugin-gfm": "1.0.2",
 | 
				
			||||||
    "unescape": "1.0.1",
 | 
					    "unescape": "1.0.1",
 | 
				
			||||||
@ -75,7 +76,7 @@
 | 
				
			|||||||
  },
 | 
					  },
 | 
				
			||||||
  "devDependencies": {
 | 
					  "devDependencies": {
 | 
				
			||||||
    "cross-env": "^7.0.2",
 | 
					    "cross-env": "^7.0.2",
 | 
				
			||||||
    "electron": "10.0.0-beta.13",
 | 
					    "electron": "10.0.0-beta.11",
 | 
				
			||||||
    "electron-builder": "22.7.0",
 | 
					    "electron-builder": "22.7.0",
 | 
				
			||||||
    "electron-packager": "15.0.0",
 | 
					    "electron-packager": "15.0.0",
 | 
				
			||||||
    "electron-rebuild": "1.11.0",
 | 
					    "electron-rebuild": "1.11.0",
 | 
				
			||||||
 | 
				
			|||||||
@ -241,7 +241,7 @@ class TreeCache {
 | 
				
			|||||||
            return null;
 | 
					            return null;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        else if (!noteId) {
 | 
					        else if (!noteId) {
 | 
				
			||||||
            console.log(`Falsy noteId ${noteId}, returning null.`);
 | 
					            console.trace(`Falsy noteId ${noteId}, returning null.`);
 | 
				
			||||||
            return null;
 | 
					            return null;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -5,6 +5,7 @@ const NoteSet = require('../note_set');
 | 
				
			|||||||
const log = require('../../log');
 | 
					const log = require('../../log');
 | 
				
			||||||
const noteCache = require('../../note_cache/note_cache');
 | 
					const noteCache = require('../../note_cache/note_cache');
 | 
				
			||||||
const protectedSessionService = require('../../protected_session');
 | 
					const protectedSessionService = require('../../protected_session');
 | 
				
			||||||
 | 
					const striptags = require('striptags');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class NoteContentProtectedFulltextExp extends Expression {
 | 
					class NoteContentProtectedFulltextExp extends Expression {
 | 
				
			||||||
    constructor(operator, tokens) {
 | 
					    constructor(operator, tokens) {
 | 
				
			||||||
@ -26,7 +27,10 @@ class NoteContentProtectedFulltextExp extends Expression {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        const sql = require('../../sql');
 | 
					        const sql = require('../../sql');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        for (let {noteId, content} of sql.iterateRows(`SELECT noteId, content FROM notes JOIN note_contents USING (noteId) WHERE isDeleted = 0 AND isProtected = 1`)) {
 | 
					        for (let {noteId, type, mime, content} of sql.iterateRows(`
 | 
				
			||||||
 | 
					                SELECT noteId, type, mime, content 
 | 
				
			||||||
 | 
					                FROM notes JOIN note_contents USING (noteId) 
 | 
				
			||||||
 | 
					                WHERE type IN ('text', 'code') AND isDeleted = 0 AND isProtected = 1`)) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            try {
 | 
					            try {
 | 
				
			||||||
                content = protectedSessionService.decryptString(content);
 | 
					                content = protectedSessionService.decryptString(content);
 | 
				
			||||||
@ -38,6 +42,11 @@ class NoteContentProtectedFulltextExp extends Expression {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
            content = content.toLowerCase();
 | 
					            content = content.toLowerCase();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            if (type === 'text' && mime === 'text/html') {
 | 
				
			||||||
 | 
					                content = striptags(content);
 | 
				
			||||||
 | 
					                content = content.replace(/ /g, ' ');
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            if (this.tokens.find(token => !content.includes(token))) {
 | 
					            if (this.tokens.find(token => !content.includes(token))) {
 | 
				
			||||||
                continue;
 | 
					                continue;
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
				
			|||||||
@ -3,7 +3,7 @@
 | 
				
			|||||||
const Expression = require('./expression');
 | 
					const Expression = require('./expression');
 | 
				
			||||||
const NoteSet = require('../note_set');
 | 
					const NoteSet = require('../note_set');
 | 
				
			||||||
const noteCache = require('../../note_cache/note_cache');
 | 
					const noteCache = require('../../note_cache/note_cache');
 | 
				
			||||||
const utils = require('../../utils');
 | 
					const striptags = require('striptags');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class NoteContentUnprotectedFulltextExp extends Expression {
 | 
					class NoteContentUnprotectedFulltextExp extends Expression {
 | 
				
			||||||
    constructor(operator, tokens) {
 | 
					    constructor(operator, tokens) {
 | 
				
			||||||
@ -18,21 +18,25 @@ class NoteContentUnprotectedFulltextExp extends Expression {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    execute(inputNoteSet) {
 | 
					    execute(inputNoteSet) {
 | 
				
			||||||
        const resultNoteSet = new NoteSet();
 | 
					        const resultNoteSet = new NoteSet();
 | 
				
			||||||
        const wheres = this.tokens.map(token => "note_contents.content LIKE " + utils.prepareSqlForLike('%', token, '%'));
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
        const sql = require('../../sql');
 | 
					        const sql = require('../../sql');
 | 
				
			||||||
console.log(`
 | 
					 | 
				
			||||||
            SELECT notes.noteId 
 | 
					 | 
				
			||||||
            FROM notes
 | 
					 | 
				
			||||||
            JOIN note_contents ON notes.noteId = note_contents.noteId
 | 
					 | 
				
			||||||
            WHERE isDeleted = 0 AND isProtected = 0 AND ${wheres.join(' AND ')}`);
 | 
					 | 
				
			||||||
        const noteIds = sql.getColumn(`
 | 
					 | 
				
			||||||
            SELECT notes.noteId 
 | 
					 | 
				
			||||||
            FROM notes
 | 
					 | 
				
			||||||
            JOIN note_contents ON notes.noteId = note_contents.noteId
 | 
					 | 
				
			||||||
            WHERE isDeleted = 0 AND isProtected = 0 AND ${wheres.join(' AND ')}`);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
        for (const noteId of noteIds) {
 | 
					        for (let {noteId, type, mime, content} of sql.iterateRows(`
 | 
				
			||||||
 | 
					                SELECT noteId, type, mime, content 
 | 
				
			||||||
 | 
					                FROM notes JOIN note_contents USING (noteId) 
 | 
				
			||||||
 | 
					                WHERE type IN ('text', 'code') AND isDeleted = 0 AND isProtected = 0`)) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            content = content.toLowerCase();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            if (type === 'text' && mime === 'text/html') {
 | 
				
			||||||
 | 
					                content = striptags(content);
 | 
				
			||||||
 | 
					                content = content.replace(/ /g, ' ');
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            if (this.tokens.find(token => !content.includes(token))) {
 | 
				
			||||||
 | 
					                continue;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            if (inputNoteSet.hasNoteId(noteId) && noteId in noteCache.notes) {
 | 
					            if (inputNoteSet.hasNoteId(noteId) && noteId in noteCache.notes) {
 | 
				
			||||||
                resultNoteSet.add(noteCache.notes[noteId]);
 | 
					                resultNoteSet.add(noteCache.notes[noteId]);
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user