refacto findWithRelationCounts

This commit is contained in:
Pierre Noël 2020-12-16 15:28:11 +01:00
parent df3a40c84b
commit 885dc5a138
6 changed files with 68 additions and 29 deletions

View File

@ -1,6 +1,8 @@
'use strict';
const pmap = require('p-map');
const { prop } = require('lodash/fp');
const { MANY_RELATIONS } = require('strapi-utils').relations.constants;
const { createQueryWithLifecycles, withLifecycles } = require('./helpers');
const { createFindPageQuery, createSearchPageQuery } = require('./paginated-queries');
@ -19,6 +21,42 @@ module.exports = function createQuery(opts) {
connectorQuery,
});
const findOrSearchWithRelationCounts = method =>
async function(params, populate) {
const xManyAssocs = [];
const xToOnePopulate = [];
model.associations
.filter(assoc => !populate || populate.includes(assoc.alias))
.forEach(assoc => {
if (MANY_RELATIONS.includes(assoc.nature)) {
xManyAssocs.push(assoc);
} else {
xToOnePopulate.push(assoc.alias);
}
});
const { results, pagination } = await this[method](params, model, xToOnePopulate);
const resultsIds = results.map(prop('id'));
const counters = await Promise.all(
xManyAssocs.map(async assoc => ({
field: assoc.alias,
counts: await this.fetchRelationCounters(assoc.alias, resultsIds),
}))
);
results.forEach(entity => {
counters.forEach(counter => {
entity[counter.field] = { count: counter.counts[entity.id] || 0 };
});
});
return {
results,
pagination,
};
};
return {
get model() {
return model;
@ -79,5 +117,11 @@ module.exports = function createQuery(opts) {
model,
fn: createSearchPageQuery(connectorQuery),
}),
searchWithRelationCounts(...args) {
return findOrSearchWithRelationCounts('searchPage').bind(this)(...args);
},
findWithRelationCounts(...args) {
return findOrSearchWithRelationCounts('findPage').bind(this)(...args);
},
};
};

View File

@ -1,6 +1,7 @@
'use strict';
const { has, pipe, prop, pick } = require('lodash/fp');
const { MANY_RELATIONS } = require('strapi-utils').relations.constants;
const {
getService,
@ -8,7 +9,6 @@ const {
setCreatorFields,
pickWritableAttributes,
} = require('../utils');
const { MANY_RELATIONS } = require('../services/constants');
const { validateBulkDeleteInput, validatePagination } = require('./validation');
module.exports = {
@ -24,36 +24,11 @@ module.exports = {
return ctx.forbidden();
}
const method = has('_q', query) ? 'searchPage' : 'findPage';
const method = has('_q', query) ? 'searchWithRelationCounts' : 'findWithRelationCounts';
const permissionQuery = permissionChecker.buildPermissionQuery(query);
const modelDef = strapi.getModel(model);
const xManyAssocs = [];
const populate = [];
modelDef.associations.forEach(assoc => {
if (MANY_RELATIONS.includes(assoc.nature)) {
xManyAssocs.push(assoc);
} else {
populate.push(assoc.alias);
}
});
const { results, pagination } = await entityManager[method](permissionQuery, model, populate);
const resultsIds = results.map(prop('id'));
const counters = await Promise.all(
xManyAssocs.map(async assoc => ({
field: assoc.alias,
counts: await strapi.query(model).fetchRelationCounters(assoc.alias, resultsIds),
}))
);
results.forEach(entity => {
counters.forEach(counter => {
entity[counter.field] = { count: counter.counts[entity.id] || 0 };
});
});
const { results, pagination } = await entityManager[method](permissionQuery, model);
ctx.body = {
results: results.map(entity => permissionChecker.sanitizeOutput(entity)),

View File

@ -52,6 +52,10 @@ module.exports = {
return strapi.entityService.findPage({ params, populate }, { model });
},
findWithRelationCounts(params, model, populate) {
return strapi.entityService.findWithRelationCounts({ params, populate }, { model });
},
search(params, model, populate) {
return strapi.entityService.search({ params, populate }, { model });
},
@ -60,6 +64,10 @@ module.exports = {
return strapi.entityService.searchPage({ params, populate }, { model });
},
searchWithRelationCounts(params, model, populate) {
return strapi.entityService.searchWithRelationCounts({ params, populate }, { model });
},
count(params, model) {
return strapi.entityService.count({ params }, { model });
},

View File

@ -32,6 +32,7 @@ const { generateTimestampCode } = require('./code-generator');
const contentTypes = require('./content-types');
const webhook = require('./webhook');
const env = require('./env-helper');
const relations = require('./relations');
module.exports = {
yup,
@ -63,4 +64,5 @@ module.exports = {
contentTypes,
webhook,
env,
relations,
};

View File

@ -3,5 +3,7 @@
const MANY_RELATIONS = ['oneToMany', 'manyToMany', 'manyWay'];
module.exports = {
MANY_RELATIONS,
constants: {
MANY_RELATIONS,
},
};

View File

@ -37,6 +37,10 @@ module.exports = ({ db, eventHub, entityValidator }) => ({
return db.query(model).findPage(params, populate);
},
findWithRelationCounts({ params, populate }, { model }) {
return db.query(model).findWithRelationCounts(params, populate);
},
/**
* Promise to fetch record
*
@ -152,6 +156,10 @@ module.exports = ({ db, eventHub, entityValidator }) => ({
return db.query(model).search(params, populate);
},
searchWithRelationCounts({ params, populate }, { model }) {
return db.query(model).searchWithRelationCounts(params, populate);
},
searchPage({ params, populate }, { model }) {
return db.query(model).searchPage(params, populate);
},