mirror of
https://github.com/zadam/trilium.git
synced 2025-03-01 14:22:32 +01:00
refactoring of router search code into service
This commit is contained in:
parent
81dc907afc
commit
62650a4545
@ -1,20 +1,13 @@
|
|||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
const sql = require('../../services/sql');
|
|
||||||
const utils = require('../../services/utils');
|
|
||||||
const noteService = require('../../services/notes');
|
const noteService = require('../../services/notes');
|
||||||
const noteCacheService = require('../../services/note_cache');
|
const noteCacheService = require('../../services/note_cache');
|
||||||
const parseFilters = require('../../services/parse_filters');
|
const searchService = require('../../services/search');
|
||||||
const buildSearchQuery = require('../../services/build_search_query');
|
|
||||||
|
|
||||||
async function searchNotes(req) {
|
async function searchNotes(req) {
|
||||||
const filters = parseFilters(req.params.searchString);
|
const noteIds = await searchService.searchForNoteIds(req.params.searchString);
|
||||||
|
|
||||||
const {query, params} = buildSearchQuery(filters);
|
return noteIds.map(noteCacheService.getNotePath).filter(res => !!res);
|
||||||
|
|
||||||
const labelFiltersNoteIds = await sql.getColumn(query, params);
|
|
||||||
|
|
||||||
return labelFiltersNoteIds.map(noteCacheService.getNotePath).filter(res => !!res);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async function saveSearchToNote(req) {
|
async function saveSearchToNote(req) {
|
||||||
|
@ -55,7 +55,7 @@ function getDesktopFileContent() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function escapePath(path) {
|
function escapePath(path) {
|
||||||
return path.replace(" ", "\\ ");
|
return path.replace(/ /g, "\\ ");
|
||||||
}
|
}
|
||||||
|
|
||||||
function getExePath() {
|
function getExePath() {
|
||||||
|
@ -2,7 +2,7 @@ const utils = require('./utils');
|
|||||||
|
|
||||||
const VIRTUAL_ATTRIBUTES = ["dateCreated", "dateCreated", "dateModified", "utcDateCreated", "utcDateModified", "isProtected", "title", "content", "type", "mime", "text"];
|
const VIRTUAL_ATTRIBUTES = ["dateCreated", "dateCreated", "dateModified", "utcDateCreated", "utcDateModified", "isProtected", "title", "content", "type", "mime", "text"];
|
||||||
|
|
||||||
module.exports = function(filters) {
|
module.exports = function(filters, selectedColumns = 'notes.*') {
|
||||||
// alias => join
|
// alias => join
|
||||||
const joins = {
|
const joins = {
|
||||||
"notes": null
|
"notes": null
|
||||||
@ -54,7 +54,7 @@ module.exports = function(filters) {
|
|||||||
if (orderByFilter) {
|
if (orderByFilter) {
|
||||||
orderBy = orderByFilter.value.split(",").map(prop => {
|
orderBy = orderByFilter.value.split(",").map(prop => {
|
||||||
const direction = prop.includes("-") ? "DESC" : "ASC";
|
const direction = prop.includes("-") ? "DESC" : "ASC";
|
||||||
const cleanedProp = prop.trim().replace("-", "");
|
const cleanedProp = prop.trim().replace(/-/g, "");
|
||||||
|
|
||||||
return getAccessor(cleanedProp) + " " + direction;
|
return getAccessor(cleanedProp) + " " + direction;
|
||||||
});
|
});
|
||||||
@ -101,17 +101,17 @@ module.exports = function(filters) {
|
|||||||
else if (filter.operator === '*=' || filter.operator === '!*=') {
|
else if (filter.operator === '*=' || filter.operator === '!*=') {
|
||||||
where += `${accessor}`
|
where += `${accessor}`
|
||||||
+ (filter.operator.includes('!') ? ' NOT' : '')
|
+ (filter.operator.includes('!') ? ' NOT' : '')
|
||||||
+ ` LIKE '%` + filter.value + "'"; // FIXME: escaping
|
+ ` LIKE ` + utils.prepareSqlForLike('%', filter.value, '');
|
||||||
}
|
}
|
||||||
else if (filter.operator === '=*' || filter.operator === '!=*') {
|
else if (filter.operator === '=*' || filter.operator === '!=*') {
|
||||||
where += `${accessor}`
|
where += `${accessor}`
|
||||||
+ (filter.operator.includes('!') ? ' NOT' : '')
|
+ (filter.operator.includes('!') ? ' NOT' : '')
|
||||||
+ ` LIKE '` + filter.value + "%'"; // FIXME: escaping
|
+ ` LIKE '` + utils.prepareSqlForLike('', filter.value, '%');
|
||||||
}
|
}
|
||||||
else if (filter.operator === '*=*' || filter.operator === '!*=*') {
|
else if (filter.operator === '*=*' || filter.operator === '!*=*') {
|
||||||
where += `${accessor}`
|
where += `${accessor}`
|
||||||
+ (filter.operator.includes('!') ? ' NOT' : '')
|
+ (filter.operator.includes('!') ? ' NOT' : '')
|
||||||
+ ` LIKE '%` + filter.value + "%'"; // FIXME: escaping
|
+ ` LIKE ` + utils.prepareSqlForLike('%', filter.value, '%');
|
||||||
}
|
}
|
||||||
else if ([">", ">=", "<", "<="].includes(filter.operator)) {
|
else if ([">", ">=", "<", "<="].includes(filter.operator)) {
|
||||||
let floatParam;
|
let floatParam;
|
||||||
@ -141,12 +141,13 @@ module.exports = function(filters) {
|
|||||||
orderBy.push("notes.title");
|
orderBy.push("notes.title");
|
||||||
}
|
}
|
||||||
|
|
||||||
const query = `SELECT DISTINCT notes.noteId FROM notes
|
const query = `SELECT ${selectedColumns} FROM notes
|
||||||
${Object.values(joins).join('\r\n')}
|
${Object.values(joins).join('\r\n')}
|
||||||
WHERE
|
WHERE
|
||||||
notes.isDeleted = 0
|
notes.isDeleted = 0
|
||||||
AND (${where})
|
AND (${where})
|
||||||
ORDER BY ` + orderBy.join(", ");
|
GROUP BY notes.noteId
|
||||||
|
ORDER BY ${orderBy.join(", ")}`;
|
||||||
|
|
||||||
console.log(query);
|
console.log(query);
|
||||||
console.log(params);
|
console.log(params);
|
||||||
|
@ -10,7 +10,7 @@ function calculateSmartValue(v) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const keyword = match[1].toUpperCase();
|
const keyword = match[1].toUpperCase();
|
||||||
const num = match[2] ? parseInt(match[2].replace(" ", "")) : 0; // can contain spaces between sign and digits
|
const num = match[2] ? parseInt(match[2].replace(/ /g, "")) : 0; // can contain spaces between sign and digits
|
||||||
|
|
||||||
let format, date;
|
let format, date;
|
||||||
|
|
||||||
@ -23,8 +23,8 @@ function calculateSmartValue(v) {
|
|||||||
format = "YYYY-MM-DD";
|
format = "YYYY-MM-DD";
|
||||||
}
|
}
|
||||||
else if (keyword === 'WEEK') {
|
else if (keyword === 'WEEK') {
|
||||||
// FIXME
|
// FIXME: this will always use sunday as start of the week
|
||||||
//date = dayjs().add(num, 'day');
|
date = dayjs().startOf('week').add(7 * num, 'day');
|
||||||
format = "YYYY-MM-DD";
|
format = "YYYY-MM-DD";
|
||||||
}
|
}
|
||||||
else if (keyword === 'MONTH') {
|
else if (keyword === 'MONTH') {
|
||||||
@ -43,6 +43,18 @@ function calculateSmartValue(v) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
module.exports = function (searchText) {
|
module.exports = function (searchText) {
|
||||||
|
// if the string doesn't start with attribute then we consider it as just standard full text search
|
||||||
|
if (!searchText.trim().startsWith("@")) {
|
||||||
|
return [
|
||||||
|
{
|
||||||
|
relation: 'and',
|
||||||
|
name: 'text',
|
||||||
|
operator: '=',
|
||||||
|
value: searchText
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
const filters = [];
|
const filters = [];
|
||||||
|
|
||||||
function trimQuotes(str) { return str.startsWith('"') ? str.substr(1, str.length - 2) : str; }
|
function trimQuotes(str) { return str.startsWith('"') ? str.substr(1, str.length - 2) : str; }
|
||||||
@ -67,7 +79,5 @@ module.exports = function (searchText) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log(filters);
|
|
||||||
|
|
||||||
return filters;
|
return filters;
|
||||||
};
|
};
|
||||||
|
25
src/services/search.js
Normal file
25
src/services/search.js
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
const repository = require('./repository');
|
||||||
|
const sql = require('./sql');
|
||||||
|
const parseFilters = require('./parse_filters');
|
||||||
|
const buildSearchQuery = require('./build_search_query');
|
||||||
|
|
||||||
|
async function searchForNotes(searchString) {
|
||||||
|
const filters = parseFilters(searchString);
|
||||||
|
|
||||||
|
const {query, params} = buildSearchQuery(filters);
|
||||||
|
|
||||||
|
return await repository.getEntities(query, params);
|
||||||
|
}
|
||||||
|
|
||||||
|
async function searchForNoteIds(searchString) {
|
||||||
|
const filters = parseFilters(searchString);
|
||||||
|
|
||||||
|
const {query, params} = buildSearchQuery(filters, 'notes.noteId');
|
||||||
|
|
||||||
|
return await sql.getColumn(query, params);
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
searchForNotes,
|
||||||
|
searchForNoteIds
|
||||||
|
};
|
@ -50,7 +50,17 @@ function isEmptyOrWhitespace(str) {
|
|||||||
|
|
||||||
function sanitizeSql(str) {
|
function sanitizeSql(str) {
|
||||||
// should be improved or usage eliminated
|
// should be improved or usage eliminated
|
||||||
return str.replace(/'/g, "\\'");
|
return str.replace(/'/g, "''");
|
||||||
|
}
|
||||||
|
|
||||||
|
function prepareSqlForLike(prefix, str, suffix) {
|
||||||
|
const value = str
|
||||||
|
.replace(/\\/g, "\\\\")
|
||||||
|
.replace(/'/g, "''")
|
||||||
|
.replace(/_/g, "\\_")
|
||||||
|
.replace(/%/g, "\\%");
|
||||||
|
|
||||||
|
return `'${prefix}${value}${suffix}' ESCAPE '\\'`;
|
||||||
}
|
}
|
||||||
|
|
||||||
async function stopWatch(what, func) {
|
async function stopWatch(what, func) {
|
||||||
@ -156,6 +166,7 @@ module.exports = {
|
|||||||
hash,
|
hash,
|
||||||
isEmptyOrWhitespace,
|
isEmptyOrWhitespace,
|
||||||
sanitizeSql,
|
sanitizeSql,
|
||||||
|
prepareSqlForLike,
|
||||||
stopWatch,
|
stopWatch,
|
||||||
escapeHtml,
|
escapeHtml,
|
||||||
unescapeHtml,
|
unescapeHtml,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user