@tasolutions/express-core
Version:
All libs for express
310 lines (265 loc) • 11.9 kB
JavaScript
;
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;