2021-01-22 19:41:11 +02:00
|
|
|
import SearchEngine from './SearchEngine';
|
|
|
|
import Note from '../../models/Note';
|
2021-05-13 14:23:17 +02:00
|
|
|
import Setting from '../../models/Setting';
|
2018-12-16 19:32:42 +02:00
|
|
|
|
2023-09-25 00:22:36 +02:00
|
|
|
export interface NotesForQueryOptions {
|
|
|
|
fields?: string[];
|
|
|
|
appendWildCards?: boolean;
|
|
|
|
}
|
|
|
|
|
2021-01-22 19:41:11 +02:00
|
|
|
export default class SearchEngineUtils {
|
2023-09-25 00:22:36 +02:00
|
|
|
public static async notesForQuery(query: string, applyUserSettings: boolean, options: NotesForQueryOptions = null, searchEngine: SearchEngine = null) {
|
|
|
|
options = {
|
|
|
|
appendWildCards: false,
|
|
|
|
...options,
|
|
|
|
};
|
2019-02-24 14:24:55 +02:00
|
|
|
|
2021-05-13 14:23:17 +02:00
|
|
|
if (!searchEngine) {
|
|
|
|
searchEngine = SearchEngine.instance();
|
|
|
|
}
|
|
|
|
|
2020-04-18 13:45:54 +02:00
|
|
|
let searchType = SearchEngine.SEARCH_TYPE_FTS;
|
|
|
|
if (query.length && query[0] === '/') {
|
|
|
|
query = query.substr(1);
|
|
|
|
searchType = SearchEngine.SEARCH_TYPE_BASIC;
|
|
|
|
}
|
|
|
|
|
2023-09-25 00:22:36 +02:00
|
|
|
const results = await searchEngine.search(query, {
|
|
|
|
searchType,
|
|
|
|
appendWildCards: options.appendWildCards,
|
|
|
|
});
|
2021-05-13 14:23:17 +02:00
|
|
|
|
2021-01-22 19:41:11 +02:00
|
|
|
const noteIds = results.map((n: any) => n.id);
|
2018-12-16 19:32:42 +02:00
|
|
|
|
2019-02-24 14:37:37 +02:00
|
|
|
// We need at least the note ID to be able to sort them below so if not
|
|
|
|
// present in field list, add it.L 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;
|
|
|
|
}
|
|
|
|
|
2021-06-07 11:21:24 +02:00
|
|
|
// 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;
|
|
|
|
}
|
|
|
|
|
2021-06-11 01:24:50 +02:00
|
|
|
let todoCompletedAutoAdded = false;
|
2021-06-07 11:21:24 +02:00
|
|
|
if (fields.indexOf('todo_completed') < 0) {
|
|
|
|
fields.push('todo_completed');
|
2021-06-11 01:24:50 +02:00
|
|
|
todoCompletedAutoAdded = true;
|
2021-06-07 11:21:24 +02:00
|
|
|
}
|
|
|
|
|
2023-09-25 00:22:36 +02:00
|
|
|
const previewOptions: any = { order: [],
|
2020-04-18 13:45:54 +02:00
|
|
|
fields: fields,
|
2023-06-01 13:02:36 +02:00
|
|
|
conditions: [`id IN ("${noteIds.join('","')}")`], ...options };
|
2018-12-16 19:32:42 +02:00
|
|
|
|
|
|
|
const notes = await Note.previews(null, previewOptions);
|
|
|
|
|
2021-06-07 11:21:24 +02:00
|
|
|
// 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));
|
|
|
|
}
|
|
|
|
|
2018-12-16 19:32:42 +02:00
|
|
|
// 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 = [];
|
2021-06-07 11:21:24 +02:00
|
|
|
for (let i = 0; i < filteredNotes.length; i++) {
|
|
|
|
const idx = noteIds.indexOf(filteredNotes[i].id);
|
|
|
|
sortedNotes[idx] = filteredNotes[i];
|
2019-02-24 14:37:37 +02:00
|
|
|
if (idWasAutoAdded) delete sortedNotes[idx].id;
|
2021-06-11 01:24:50 +02:00
|
|
|
if (todoCompletedAutoAdded) delete sortedNotes[idx].todo_completed;
|
|
|
|
if (isTodoAutoAdded) delete sortedNotes[idx].is_todo;
|
2021-05-13 14:23:17 +02:00
|
|
|
}
|
2020-08-19 00:53:28 +02:00
|
|
|
|
2021-06-24 14:22:35 +02:00
|
|
|
// 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 sortedNotes.filter(n => n);
|
2018-12-16 19:32:42 +02:00
|
|
|
}
|
|
|
|
}
|