UNPKG

@tasolutions/express-core

Version:
310 lines (265 loc) 11.9 kB
'use strict'; const { searchByObjectIdField } = require('./collection.util'); const stringHelper = require('./string.helper'); const _ = require('lodash'); const queryUtil = { /** * This function get query by date from ... to * @param query * @param field_name * @param field_name_from * @param field_name_to * @returns {query} */ dateFromTo: (query, field_name, field_name_from, field_name_to) => { if (query[`${field_name_from}`] && !stringHelper.isValidDate(query[`${field_name_from}`])) throw { message: `${field_name_from} invalid.` }; if (query[`${field_name_to}`] && !stringHelper.isValidDate(query[`${field_name_to}`])) throw { message: `${field_name_to} invalid.` }; if (query[`${field_name_from}`]) query[`${field_name}`] = { '$gte': new Date(query[`${field_name_from}`]) }; if (query[`${field_name_to}`]) query[`${field_name}`] = { '$lte': new Date(query[`${field_name_to}`]) }; if (query[`${field_name_from}`] && query[`${field_name_to}`]) query[`${field_name}`] = { '$gte': new Date(query[`${field_name_from}`]), '$lte': new Date(query[`${field_name_to}`]) }; return query; }, /** * This function get query by number from ... to * @param query * @param field_name * @param field_name_from * @param field_name_to * @returns {*} */ numberFromTo: (query, field_name, field_name_from, field_name_to) => { if (query[`${field_name_from}`] && isNaN(query[`${field_name_from}`])) throw { message: `${field_name_from} invalid.` }; if (query[`${field_name_to}`] && isNaN(query[`${field_name_to}`])) throw { message: `${field_name_to} invalid.` }; if (query[`${field_name_from}`]) query[`${field_name}`] = { '$gte': Number(query[`${field_name_from}`]).valueOf() }; if (query[`${field_name_to}`]) query[`${field_name}`] = { '$lte': Number(query[`${field_name_to}`]).valueOf() }; if (query[`${field_name_from}`] && query[`${field_name_to}`]) query[`${field_name}`] = { '$gte': Number(query[`${field_name_from}`]).valueOf(), '$lte': Number(query[`${field_name_to}`]).valueOf() }; return query; }, /** * This function get query like content * @param query * @param field_name */ whereLike: (query, field_name) => { let newQuery = {}; newQuery[`${field_name}`] = {}; if (query[`${field_name}`]) newQuery[`${field_name}`]['$regex'] = new RegExp(query[`${field_name}`], 'i'); return _.isEmpty(newQuery[`${field_name}`]) ? query : { ...query, ...newQuery, }; }, /** * This function search * @param query * @param field_name */ search: (Collection, search) => { // Split the search string into individual terms. const searchTerms = search.includes(';') ? search.split(';').map(term => term.trim()).filter(term => term !== '') : [search]; // Get the schema keys and exclude certain default keys. let keySchema = Object.keys(Collection.schema.tree); keySchema = _.without(keySchema, 'id', '_id', '__v', 'updatedAt', 'createdAt', 'updated_at', 'created_at'); // Get the virtual keys and exclude them from the schema keys. const keyVirtuals = Object.keys(Collection.schema.virtuals) keySchema = keySchema.filter(item => !keyVirtuals.includes(item)); let arrSearch = []; const objectIdTypes = ['ObjectId', 'ObjectID', 'Date']; // Iterate over each term and construct search queries. searchTerms.forEach(searchTerm => { let regex = new RegExp(searchTerm, 'i'); for (let i = 0; i < keySchema.length; i++) { const fieldKeys = Object.keys(Collection.schema.tree[`${keySchema[i]}`]); for (let j = 0; j < fieldKeys.length; j++) { const path = Collection.schema.path(`${keySchema[i]}.${fieldKeys[j]}`); if (!path) continue; const isInstance = path.instance; switch (isInstance) { case 'String': arrSearch.push({ [`${keySchema[i]}.${fieldKeys[j]}`]: regex }); break; default: break; } } const path = Collection.schema.path(keySchema[i]); if (!path) continue; const isInstance = path.instance; switch (isInstance) { case 'String': arrSearch.push({ [keySchema[i]]: regex }); break; case 'Number': if (!isNaN(searchTerm)) arrSearch.push({ [keySchema[i]]: Number(searchTerm) }); break; case 'Array': const pathChild = Collection.schema.path(`${keySchema[i]}`); if (pathChild && pathChild.casterConstructor && objectIdTypes.includes(pathChild.casterConstructor.schemaName)) { continue; } arrSearch.push({ [keySchema[i]]: { $in: [regex] } }); break; default: break; } } }); let query = { $or: arrSearch }; return query; }, /** * This function populateField * @param query * @param field_name */ populateField: (Collection) => { let keySchema = Object.keys(Collection.schema.tree); keySchema = _.without(keySchema, 'id', '_id', '__v', 'updatedAt', 'createdAt', 'updated_at', 'created_at', 'files'); const keyVirtuals = Object.keys(Collection.schema.virtuals); keySchema = keySchema.filter(item => !keyVirtuals.includes(item)); const objectIdTypes = ['ObjectId', 'ObjectID']; let results = []; for (let i = 0; i < keySchema.length; i++) { const path = Collection.schema.path(keySchema[i]); if (!path) continue; const isInstance = path.instance; if (isInstance === 'Array' && path.caster && objectIdTypes.includes(path.caster.instance)) { results.push(keySchema[i]); } if (objectIdTypes.includes(isInstance)) { results.push(keySchema[i]); } } return results; }, /** * This function get query by date from ... to * @param query * @param field_name * @param field_name_from * @param field_name_to * @returns {query} */ queryDateFromTo: (query, field_name) => { const field_name_from = `${field_name}_from`; const field_name_to = `${field_name}_to`; if (query[`${field_name_from}`] && !stringHelper.isValidDate(query[`${field_name_from}`])) throw { message: `${field_name_from} invalid.` }; if (query[`${field_name_to}`] && !stringHelper.isValidDate(query[`${field_name_to}`])) throw { message: `${field_name_to} invalid.` }; if (query[`${field_name_from}`]) query[`${field_name}`] = { '$gte': new Date(query[`${field_name_from}`]) }; if (query[`${field_name_to}`]) query[`${field_name}`] = { '$lte': new Date(query[`${field_name_to}`]) }; if (query[`${field_name_from}`] && query[`${field_name_to}`]) query[`${field_name}`] = { '$gte': new Date(query[`${field_name_from}`]), '$lte': new Date(query[`${field_name_to}`]) }; query = _.omit(query, [field_name_from, field_name_to]); return query; }, /** * This function get query by number from ... to * @param query * @param field_name * @param field_name_from * @param field_name_to * @returns {*} */ queryNumberFromTo: (query, field_name) => { const field_name_from = `${field_name}_from`; const field_name_to = `${field_name}_to`; if (query[`${field_name_from}`] && isNaN(query[`${field_name_from}`])) throw { message: `${field_name_from} invalid.` }; if (query[`${field_name_to}`] && isNaN(query[`${field_name_to}`])) throw { message: `${field_name_to} invalid.` }; if (query[`${field_name_from}`]) query[`${field_name}`] = { '$gte': Number(query[`${field_name_from}`]).valueOf() }; if (query[`${field_name_to}`]) query[`${field_name}`] = { '$lte': Number(query[`${field_name_to}`]).valueOf() }; if (query[`${field_name_from}`] && query[`${field_name_to}`]) query[`${field_name}`] = { '$gte': Number(query[`${field_name_from}`]).valueOf(), '$lte': Number(query[`${field_name_to}`]).valueOf() }; query = _.omit(query, [field_name_from, field_name_to]); return query; }, /** * This function get query by enum * @param query * @param field_name * @param field_name_from * @param field_name_to * @returns {*} */ queryInEnum: (query, field_name) => { if (query[`${field_name}`]) query[`${field_name}`] = { '$in': query[`${field_name}`].split(',') }; return query; }, /** * This function get query */ getQuery: async (Collection, req) => { let query = { ...req.query }; delete query.access_token; const sortFields = Object.keys(query).filter(key => key.startsWith('sort_')); sortFields.forEach(field => delete query[field]); // Gọi hàm tìm kiếm chung query = await searchByObjectIdField(query, req, Collection); let keySchema = Object.keys(Collection.schema.tree); keySchema = _.without(keySchema, 'id', '_id', '__v'); const keyVirtuals = Object.keys(Collection.schema.virtuals); keySchema = keySchema.filter(item => !keyVirtuals.includes(item)); keySchema.forEach(key => { const path = Collection.schema.path(key); if (!path) return; switch (path.instance) { case 'Date': query = queryUtil.queryDateFromTo(query, key); delete req.query[`${key}_from`]; delete req.query[`${key}_to`]; break; case 'String': if (path.enumValues) { query = queryUtil.queryInEnum(query, key); } else { query = queryUtil.whereLike(query, key); } break; case 'Number': query = queryUtil.queryNumberFromTo(query, key); delete req.query[`${key}_from`]; delete req.query[`${key}_to`]; break; default: break; } }); return query; }, /** * This function get getSort */ getSort: (req, configs = {}) => { const query = { ...req.query }; const sortFields = Object.keys(query).filter(key => key.startsWith('sort_')); let results = sortFields.map(field => { const strippedField = field.slice(5); return [strippedField, query[field]]; }); if (configs.sort) { let configSorts; if (Array.isArray(configs.sort[0])) { configSorts = configs.sort; } else { configSorts = _.chunk(configs.sort, 2); } results = results.concat(configSorts); } return results; }, }; module.exports = queryUtil;