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'; 'use strict';
const _ = require('lodash'); const _ = require('lodash');
const { isEmpty, set, omit, reduce } = require('lodash/fp'); const { isEmpty, set, omit, assoc } = require('lodash/fp');
const semver = require('semver'); const semver = require('semver');
const { const {
hasDeepFilters, hasDeepFilters,
@ -94,9 +94,8 @@ const buildQuery = ({
aggregate = false, aggregate = false,
} = {}) => { } = {}) => {
const search = buildSearchOr(model, searchParam); 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 }); return buildSimpleQuery({ model, filters, search, populate });
} }
@ -117,9 +116,11 @@ const buildSimpleQuery = ({ model, filters, search, populate }) => {
const wheres = where.map(buildWhereClause); const wheres = where.map(buildWhereClause);
const findCriteria = combineSearchAndWhere(search, wheres); const findCriteria = combineSearchAndWhere(search, wheres);
let query = model let query = model
.find(findCriteria, null, { publicationState: filters.publicationState }) .find(findCriteria, null, { publicationState: filters.publicationState })
.populate(populate); .populate(populate);
query = applyQueryParams({ model, query, filters }); query = applyQueryParams({ model, query, filters });
return Object.assign(query, { return Object.assign(query, {
@ -145,13 +146,13 @@ const buildDeepQuery = ({ model, filters, search, populate }) => {
where: filters.where, where: filters.where,
}); });
const aggregateOptions = {
paths: _.merge({}, populatePaths, wherePaths),
};
// Init the query // Init the query
let query = model let query = model
.aggregate( .aggregate(buildQueryAggregate(model, filters, aggregateOptions))
buildQueryAggregate(model, filters, {
paths: _.merge({}, populatePaths, wherePaths),
})
)
.append(buildQueryMatches(model, filters, search)) .append(buildQueryMatches(model, filters, search))
.append(buildQuerySort(model, filters)); .append(buildQuerySort(model, filters));
@ -161,39 +162,21 @@ const buildDeepQuery = ({ model, filters, search, populate }) => {
*/ */
then(...args) { then(...args) {
return query return query
.append({ .append({ $project: { _id: true } })
$project: { _id: true },
})
.then(results => results.map(el => el._id)) .then(results => results.map(el => el._id))
.then(ids => { .then(ids => {
if (ids.length === 0) return []; if (ids.length === 0) return [];
const query = model const idsMap = ids.reduce((acc, id, idx) => assoc(id, idx, acc), {});
.find(
{
_id: {
$in: ids,
},
},
null
)
.populate(populate);
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 return query.then(orderByIndexMap(idsMap));
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;
}, [])
)
);
}) })
.then(...args); .then(...args);
}, },
@ -719,4 +702,16 @@ const findModelPath = ({ rootModel, path }) => {
return tmpPath.length > 0 ? tmpPath.join('.') : null; 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; module.exports = buildQuery;

View File

@ -92,7 +92,7 @@ const normalizeFieldName = ({ model, field }) => {
const BOOLEAN_OPERATORS = ['or']; 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 // 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 // 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 // Validate query clauses
if ([where, sort].some(Array.isArray)) { if ([where, sort].some(Array.isArray)) {
if (hasDeepFilters({ where, sort, minDepth: 2 })) { if (hasDeepFilters({ where, sort }, { minDepth: 2 })) {
strapi.log.warn( 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.' '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.'
); );