From 83b7353f3fbaa3a7e4e2a8ffe746ff847d5dcd0d Mon Sep 17 00:00:00 2001 From: Andris Reinman Date: Thu, 27 Apr 2023 15:24:28 +0300 Subject: [PATCH] Initial search query parser --- lib/api/messages.js | 5 ++--- lib/search-query.js | 13 ++++++++++++- lib/tasks/search-apply.js | 13 ++++++++++++- 3 files changed, 26 insertions(+), 5 deletions(-) diff --git a/lib/api/messages.js b/lib/api/messages.js index e1809cf6..87b43fba 100644 --- a/lib/api/messages.js +++ b/lib/api/messages.js @@ -508,6 +508,8 @@ module.exports = (db, server, messageHandler, userHandler, storageHandler, setti const searchSchema = Joi.object().keys({ user: Joi.string().hex().lowercase().length(24).required(), + q: Joi.string().trim().empty('').max(1024).optional(), + mailbox: Joi.string().hex().length(24).empty(''), thread: Joi.string().hex().length(24).empty(''), @@ -540,7 +542,6 @@ module.exports = (db, server, messageHandler, userHandler, storageHandler, setti res.charSet('utf-8'); const schema = searchSchema.keys({ - q: Joi.string().trim().empty('').max(1024).optional(), threadCounters: booleanSchema.default(false), limit: Joi.number().default(20).min(1).max(250), order: Joi.any().empty('').allow('asc', 'desc').optional(), @@ -591,8 +592,6 @@ module.exports = (db, server, messageHandler, userHandler, storageHandler, setti query = prepared.query; } - console.log('SEARCH FILTER', JSON.stringify(filter)); - let total = await getFilteredMessageCount(filter); log.verbose('API', 'Searching %s', JSON.stringify(filter)); diff --git a/lib/search-query.js b/lib/search-query.js index d6541f45..69e62a3f 100644 --- a/lib/search-query.js +++ b/lib/search-query.js @@ -142,6 +142,8 @@ function parseSearchQuery(queryStr) { const getMongoDBQuery = async (db, user, queryStr) => { const parsed = parseSearchQuery(queryStr); + let hasTextFilter = false; + let walkTree = async node => { if (Array.isArray(node)) { let branches = []; @@ -185,6 +187,8 @@ const getMongoDBQuery = async (db, user, queryStr) => { branch = { $not: branch }; } + hasTextFilter = true; + return branch; } else if (node.keywords) { let branches = []; @@ -298,7 +302,14 @@ const getMongoDBQuery = async (db, user, queryStr) => { }; if (parsed && parsed.length) { - return Object.assign({ user: null }, await walkTree(Array.isArray(parsed) ? { $and: parsed } : parsed), { user }); + let filter = await walkTree(Array.isArray(parsed) ? { $and: parsed } : parsed); + + let extras = { user }; + if (hasTextFilter) { + extras.searchable = true; + } + + return Object.assign({ user: null }, filter, extras); } return { user: false }; diff --git a/lib/tasks/search-apply.js b/lib/tasks/search-apply.js index f71545fc..5561ccaa 100644 --- a/lib/tasks/search-apply.js +++ b/lib/tasks/search-apply.js @@ -4,6 +4,7 @@ const log = require('npmlog'); const db = require('../db'); const util = require('util'); const prepareSearchFilter = require('../prepare-search-filter'); +const { getMongoDBQuery } = require('../search-query'); const ObjectId = require('mongodb').ObjectId; let run = async (task, data, options) => { @@ -22,7 +23,17 @@ let run = async (task, data, options) => { action.moveTo = new ObjectId(action.moveTo); } - const { query, filter } = await prepareSearchFilter(db, user, data); + let query; + let filter; + + if (data.q) { + filter = await getMongoDBQuery(db, user, data.q); + query = data.q; + } else { + let prepared = await prepareSearchFilter(db, user, data); + filter = prepared.filter; + query = prepared.query; + } try { // getMailboxAsync throws if mailbox is missing or wrong owner