1
0
mirror of https://github.com/laurent22/joplin.git synced 2024-12-24 10:27:10 +02:00
joplin/packages/lib/services/search/SearchEngineUtils.ts

93 lines
3.1 KiB
TypeScript

import SearchEngine from './SearchEngine';
import Note from '../../models/Note';
import Setting from '../../models/Setting';
export interface NotesForQueryOptions {
fields?: string[];
appendWildCards?: boolean;
}
export default class SearchEngineUtils {
public static async notesForQuery(query: string, applyUserSettings: boolean, options: NotesForQueryOptions = null, searchEngine: SearchEngine = null) {
options = {
appendWildCards: false,
...options,
};
if (!searchEngine) {
searchEngine = SearchEngine.instance();
}
let searchType = SearchEngine.SEARCH_TYPE_FTS;
if (query.length && query[0] === '/') {
query = query.substr(1);
searchType = SearchEngine.SEARCH_TYPE_BASIC;
}
const results = await searchEngine.search(query, {
searchType,
appendWildCards: options.appendWildCards,
});
const noteIds = results.map(n => n.id);
// We need at least the note ID to be able to sort them below so if not
// present in field list, add it. Also remember it was auto-added so that
// it can be removed afterwards.
let idWasAutoAdded = false;
const fields = options.fields ? options.fields : Note.previewFields().slice();
if (fields.indexOf('id') < 0) {
fields.push('id');
idWasAutoAdded = true;
}
// Add fields is_todo and todo_completed for showCompletedTodos filtering.
// Also remember that the field was auto-added so that it can be removed afterwards.
let isTodoAutoAdded = false;
if (fields.indexOf('is_todo') < 0) {
fields.push('is_todo');
isTodoAutoAdded = true;
}
let todoCompletedAutoAdded = false;
if (fields.indexOf('todo_completed') < 0) {
fields.push('todo_completed');
todoCompletedAutoAdded = true;
}
// eslint-disable-next-line @typescript-eslint/no-explicit-any -- Old code before rule was applied
const previewOptions: any = { order: [],
fields: fields,
conditions: [`id IN ("${noteIds.join('","')}")`], ...options };
const notes = await Note.previews(null, previewOptions);
// Filter completed todos
let filteredNotes = [...notes];
if (applyUserSettings && !Setting.value('showCompletedTodos')) {
filteredNotes = notes.filter(note => note.is_todo === 0 || (note.is_todo === 1 && note.todo_completed === 0));
}
// By default, the notes will be returned in reverse order
// or maybe random order so sort them here in the correct order
// (search engine returns the results in order of relevance).
const sortedNotes = [];
for (let i = 0; i < filteredNotes.length; i++) {
const idx = noteIds.indexOf(filteredNotes[i].id);
sortedNotes[idx] = filteredNotes[i];
if (idWasAutoAdded) delete sortedNotes[idx].id;
if (todoCompletedAutoAdded) delete sortedNotes[idx].todo_completed;
if (isTodoAutoAdded) delete sortedNotes[idx].is_todo;
}
// Note that when the search engine index is somehow corrupted, it might
// contain references to notes that don't exist. Not clear how it can
// happen, but anyway handle it here. Was causing this issue:
// https://discourse.joplinapp.org/t/how-to-recover-corrupted-database/9367
return {
notes: sortedNotes.filter(n => n),
results,
};
}
}