Small refactoring to make the code easier to read

This commit is contained in:
Alexandre Bodin 2020-12-10 11:17:41 +01:00
parent a415638848
commit e630cee0c9
2 changed files with 32 additions and 37 deletions

View File

@ -1,7 +1,7 @@
'use strict';
const _ = require('lodash');
const { isEmpty, set, omit, reduce } = require('lodash/fp');
const { isEmpty, set, omit, assoc } = require('lodash/fp');
const semver = require('semver');
const {
hasDeepFilters,
@ -94,9 +94,8 @@ const buildQuery = ({
aggregate = false,
} = {}) => {
const search = buildSearchOr(model, searchParam);
const { where, sort } = filters;
if (!hasDeepFilters({ where, sort }) && aggregate === false) {
if (!hasDeepFilters(filters) && aggregate === false) {
return buildSimpleQuery({ model, filters, search, populate });
}
@ -117,9 +116,11 @@ const buildSimpleQuery = ({ model, filters, search, populate }) => {
const wheres = where.map(buildWhereClause);
const findCriteria = combineSearchAndWhere(search, wheres);
let query = model
.find(findCriteria, null, { publicationState: filters.publicationState })
.populate(populate);
query = applyQueryParams({ model, query, filters });
return Object.assign(query, {
@ -145,13 +146,13 @@ const buildDeepQuery = ({ model, filters, search, populate }) => {
where: filters.where,
});
const aggregateOptions = {
paths: _.merge({}, populatePaths, wherePaths),
};
// Init the query
let query = model
.aggregate(
buildQueryAggregate(model, filters, {
paths: _.merge({}, populatePaths, wherePaths),
})
)
.aggregate(buildQueryAggregate(model, filters, aggregateOptions))
.append(buildQueryMatches(model, filters, search))
.append(buildQuerySort(model, filters));
@ -161,39 +162,21 @@ const buildDeepQuery = ({ model, filters, search, populate }) => {
*/
then(...args) {
return query
.append({
$project: { _id: true },
})
.append({ $project: { _id: true } })
.then(results => results.map(el => el._id))
.then(ids => {
if (ids.length === 0) return [];
const query = model
.find(
{
_id: {
$in: ids,
},
},
null
)
.populate(populate);
const idsMap = ids.reduce((acc, id, idx) => assoc(id, idx, acc), {});
const idsMapper = ids.reduce((acc, id, idx) => ({ ...acc, [id]: idx }), {});
const mongooseQuery = model.find({ _id: { $in: ids } }, null).populate(populate);
const query = applyQueryParams({
model,
query: mongooseQuery,
filters: omit('sort', filters),
});
// Remove sort filters since they've already been processed
const filtersNoSort = omit('sort', filters);
return (
applyQueryParams({ model, query, filters: filtersNoSort })
// Reorder results using `ids` order
.then(
reduce((acc, entry) => {
acc[idsMapper[entry._id]] = entry;
return acc;
}, [])
)
);
return query.then(orderByIndexMap(idsMap));
})
.then(...args);
},
@ -719,4 +702,16 @@ const findModelPath = ({ rootModel, path }) => {
return tmpPath.length > 0 ? tmpPath.join('.') : null;
};
/**
* Order a list of entites based on an indexMap
* @param {Object[]} entities - A list of entities
* @param {Object} indexMap - index map of the form { [id]: index }
*/
const orderByIndexMap = indexMap => entities => {
return entities.reduce((acc, entry) => {
acc[indexMap[entry._id]] = entry;
return acc;
}, []);
};
module.exports = buildQuery;

View File

@ -92,7 +92,7 @@ const normalizeFieldName = ({ model, field }) => {
const BOOLEAN_OPERATORS = ['or'];
const hasDeepFilters = ({ where = [], sort = [], minDepth = 1 } = {}) => {
const hasDeepFilters = ({ where = [], sort = [] }, { minDepth = 1 } = {}) => {
// A query uses deep filtering if some of the clauses contains a sort or a match expression on a field of a relation
// We don't use minDepth here because deep sorting is limited to depth 1
@ -167,7 +167,7 @@ const buildQuery = ({ model, filters = {}, ...rest }) => {
// Validate query clauses
if ([where, sort].some(Array.isArray)) {
if (hasDeepFilters({ where, sort, minDepth: 2 })) {
if (hasDeepFilters({ where, sort }, { minDepth: 2 })) {
strapi.log.warn(
'Deep filtering queries should be used carefully (e.g Can cause performance issues).\nWhen possible build custom routes which will in most case be more optimised.'
);