mirror of
https://github.com/strapi/strapi.git
synced 2025-09-26 08:52:26 +00:00
Fix deepFiltering with draft & publish
Signed-off-by: Convly <jean-sebastien.herbaux@epitech.eu>
This commit is contained in:
parent
fad9fda318
commit
03f5342123
@ -13,7 +13,7 @@ const BOOLEAN_OPERATORS = ['or'];
|
|||||||
const buildQuery = ({ model, filters }) => qb => {
|
const buildQuery = ({ model, filters }) => qb => {
|
||||||
if (_.has(filters, 'where') && Array.isArray(filters.where) && filters.where.length > 0) {
|
if (_.has(filters, 'where') && Array.isArray(filters.where) && filters.where.length > 0) {
|
||||||
qb.distinct();
|
qb.distinct();
|
||||||
buildJoinsAndFilter(qb, model, filters.where);
|
buildJoinsAndFilter(qb, model, filters);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_.has(filters, 'sort')) {
|
if (_.has(filters, 'sort')) {
|
||||||
@ -45,9 +45,11 @@ const buildQuery = ({ model, filters }) => qb => {
|
|||||||
* Add joins and where filters
|
* Add joins and where filters
|
||||||
* @param {Object} qb - knex query builder
|
* @param {Object} qb - knex query builder
|
||||||
* @param {Object} model - Bookshelf model
|
* @param {Object} model - Bookshelf model
|
||||||
* @param {Array<Object>} whereClauses - an array of where clause
|
* @param {Object} filters - The query filters
|
||||||
*/
|
*/
|
||||||
const buildJoinsAndFilter = (qb, model, whereClauses) => {
|
const buildJoinsAndFilter = (qb, model, filters) => {
|
||||||
|
const { where: whereClauses } = filters;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns an alias for a name (simple incremental alias name)
|
* Returns an alias for a name (simple incremental alias name)
|
||||||
* @param {string} name - name to alias
|
* @param {string} name - name to alias
|
||||||
@ -210,12 +212,29 @@ const buildJoinsAndFilter = (qb, model, whereClauses) => {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
const aliasedWhereClauses = buildWhereClauses(whereClauses, { model });
|
/**
|
||||||
|
* Add queries on tree's joins (deep search) based on given filters
|
||||||
|
* @param tree - joins tree
|
||||||
|
*/
|
||||||
|
const addFiltersQueriesToJoinTree = tree => {
|
||||||
|
_.each(tree.joins, value => {
|
||||||
|
const { alias, model } = value;
|
||||||
|
|
||||||
buildJoinsFromTree(qb, tree);
|
runPopulateQueries(
|
||||||
|
toQueries({
|
||||||
|
publicationState: { query: filters.publicationState, model, alias },
|
||||||
|
}),
|
||||||
|
qb
|
||||||
|
);
|
||||||
|
addFiltersQueriesToJoinTree(value);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const aliasedWhereClauses = buildWhereClauses(whereClauses, { model });
|
||||||
aliasedWhereClauses.forEach(w => buildWhereClause({ qb, ...w }));
|
aliasedWhereClauses.forEach(w => buildWhereClause({ qb, ...w }));
|
||||||
|
|
||||||
return;
|
buildJoinsFromTree(qb, tree);
|
||||||
|
addFiltersQueriesToJoinTree(tree);
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -11,9 +11,9 @@ const {
|
|||||||
const optionsMap = {
|
const optionsMap = {
|
||||||
publicationState: {
|
publicationState: {
|
||||||
queries: {
|
queries: {
|
||||||
[DP_PUB_STATE_LIVE]: ({ model }) => qb => {
|
[DP_PUB_STATE_LIVE]: ({ model, alias }) => qb => {
|
||||||
const { collectionName } = model;
|
const { collectionName } = model;
|
||||||
qb.whereNotNull(`${collectionName}.${PUBLISHED_AT_ATTRIBUTE}`);
|
qb.whereNotNull(`${alias || collectionName}.${PUBLISHED_AT_ATTRIBUTE}`);
|
||||||
},
|
},
|
||||||
[DP_PUB_STATE_PREVIEW]: () => null,
|
[DP_PUB_STATE_PREVIEW]: () => null,
|
||||||
},
|
},
|
||||||
|
@ -6,7 +6,10 @@ const utils = require('./utils')();
|
|||||||
const populateQueries = require('./utils/populate-queries');
|
const populateQueries = require('./utils/populate-queries');
|
||||||
const {
|
const {
|
||||||
hasDeepFilters,
|
hasDeepFilters,
|
||||||
contentTypes: { hasDraftAndPublish },
|
contentTypes: {
|
||||||
|
constants: { DP_PUB_STATES },
|
||||||
|
hasDraftAndPublish,
|
||||||
|
},
|
||||||
} = require('strapi-utils');
|
} = require('strapi-utils');
|
||||||
|
|
||||||
const combineSearchAndWhere = (search = [], wheres = []) => {
|
const combineSearchAndWhere = (search = [], wheres = []) => {
|
||||||
@ -139,7 +142,7 @@ const buildDeepQuery = ({ model, filters, search, populate }) => {
|
|||||||
// Init the query
|
// Init the query
|
||||||
let query = model
|
let query = model
|
||||||
.aggregate(
|
.aggregate(
|
||||||
buildQueryAggregate(model, {
|
buildQueryAggregate(model, filters, {
|
||||||
paths: _.merge({}, populatePaths, wherePaths),
|
paths: _.merge({}, populatePaths, wherePaths),
|
||||||
})
|
})
|
||||||
)
|
)
|
||||||
@ -292,7 +295,7 @@ const recursiveCastedWherePaths = (whereClauses, { model }) => {
|
|||||||
* Builds an object based on paths:
|
* Builds an object based on paths:
|
||||||
* [
|
* [
|
||||||
* 'articles',
|
* 'articles',
|
||||||
* 'articles.tags.cateogry',
|
* 'articles.tags.category',
|
||||||
* 'articles.tags.label',
|
* 'articles.tags.label',
|
||||||
* ] => {
|
* ] => {
|
||||||
* articles: {
|
* articles: {
|
||||||
@ -307,14 +310,15 @@ const recursiveCastedWherePaths = (whereClauses, { model }) => {
|
|||||||
const pathsToTree = paths => paths.reduce((acc, path) => _.merge(acc, _.set({}, path, {})), {});
|
const pathsToTree = paths => paths.reduce((acc, path) => _.merge(acc, _.set({}, path, {})), {});
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Builds the aggregations pipeling of the query
|
* Builds the aggregations pipeline of the query
|
||||||
* @param {Object} model - Queried model
|
* @param {Object} model - Queried model
|
||||||
|
* @param {Object} filters - The query filters
|
||||||
* @param {Object} options - Options
|
* @param {Object} options - Options
|
||||||
* @param {Object} options.paths - A tree of paths to aggregate e.g { article : { tags : { label: {}}}}
|
* @param {Object} options.paths - A tree of paths to aggregate e.g { article : { tags : { label: {}}}}
|
||||||
*/
|
*/
|
||||||
const buildQueryAggregate = (model, { paths } = {}) => {
|
const buildQueryAggregate = (model, filters, { paths } = {}) => {
|
||||||
return Object.keys(paths).reduce((acc, key) => {
|
return Object.keys(paths).reduce((acc, key) => {
|
||||||
return acc.concat(buildLookup({ model, key, paths: paths[key] }));
|
return acc.concat(buildLookup({ model, key, paths: paths[key], filters }));
|
||||||
}, []);
|
}, []);
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -325,7 +329,7 @@ const buildQueryAggregate = (model, { paths } = {}) => {
|
|||||||
* @param {string} options.key - The attribute name to lookup on the model
|
* @param {string} options.key - The attribute name to lookup on the model
|
||||||
* @param {Object} options.paths - A tree of paths to aggregate inside the current lookup e.g { { tags : { label: {}}}
|
* @param {Object} options.paths - A tree of paths to aggregate inside the current lookup e.g { { tags : { label: {}}}
|
||||||
*/
|
*/
|
||||||
const buildLookup = ({ model, key, paths }) => {
|
const buildLookup = ({ model, key, paths, filters }) => {
|
||||||
const assoc = model.associations.find(a => a.alias === key);
|
const assoc = model.associations.find(a => a.alias === key);
|
||||||
const assocModel = strapi.db.getModelByAssoc(assoc);
|
const assocModel = strapi.db.getModelByAssoc(assoc);
|
||||||
|
|
||||||
@ -341,8 +345,8 @@ const buildLookup = ({ model, key, paths }) => {
|
|||||||
localAlias: `$${assoc.alias}`,
|
localAlias: `$${assoc.alias}`,
|
||||||
},
|
},
|
||||||
pipeline: []
|
pipeline: []
|
||||||
.concat(buildLookupMatch({ assoc }))
|
.concat(buildLookupMatch({ assoc, assocModel, filters }))
|
||||||
.concat(buildQueryAggregate(assocModel, { paths })),
|
.concat(buildQueryAggregate(assocModel, filters, { paths })),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
@ -351,17 +355,29 @@ const buildLookup = ({ model, key, paths }) => {
|
|||||||
/**
|
/**
|
||||||
* Build a lookup match expression (equivalent to a SQL join condition)
|
* Build a lookup match expression (equivalent to a SQL join condition)
|
||||||
* @param {Object} options - Options
|
* @param {Object} options - Options
|
||||||
* @param {Object} options.assoc - The association on which is based the ematching xpression
|
* @param {Object} options.assoc - The association on which is based the matching expression
|
||||||
*/
|
*/
|
||||||
const buildLookupMatch = ({ assoc }) => {
|
const buildLookupMatch = ({ assoc, assocModel, filters = {} }) => {
|
||||||
|
const defaultMatches = [];
|
||||||
|
|
||||||
|
if (hasDraftAndPublish(assocModel) && DP_PUB_STATES.includes(filters.publicationState)) {
|
||||||
|
const dpQuery = populateQueries.publicationState[filters.publicationState];
|
||||||
|
|
||||||
|
if (_.isObject(dpQuery)) {
|
||||||
|
defaultMatches.push(dpQuery);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
switch (assoc.nature) {
|
switch (assoc.nature) {
|
||||||
case 'oneToOne': {
|
case 'oneToOne': {
|
||||||
return [
|
return [
|
||||||
{
|
{
|
||||||
$match: {
|
$match: {
|
||||||
$expr: {
|
$and: defaultMatches.concat({
|
||||||
$eq: [`$${assoc.via}`, '$$localId'],
|
$expr: {
|
||||||
},
|
$eq: [`$${assoc.via}`, '$$localId'],
|
||||||
|
},
|
||||||
|
}),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
@ -369,9 +385,11 @@ const buildLookupMatch = ({ assoc }) => {
|
|||||||
case 'oneToMany': {
|
case 'oneToMany': {
|
||||||
return {
|
return {
|
||||||
$match: {
|
$match: {
|
||||||
$expr: {
|
$and: defaultMatches.concat({
|
||||||
$eq: [`$${assoc.via}`, '$$localId'],
|
$expr: {
|
||||||
},
|
$eq: [`$${assoc.via}`, '$$localId'],
|
||||||
|
},
|
||||||
|
}),
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@ -379,18 +397,22 @@ const buildLookupMatch = ({ assoc }) => {
|
|||||||
case 'manyToOne': {
|
case 'manyToOne': {
|
||||||
return {
|
return {
|
||||||
$match: {
|
$match: {
|
||||||
$expr: {
|
$and: defaultMatches.concat({
|
||||||
$eq: ['$$localAlias', '$_id'],
|
$expr: {
|
||||||
},
|
$eq: ['$$localAlias', '$_id'],
|
||||||
|
},
|
||||||
|
}),
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
case 'manyWay': {
|
case 'manyWay': {
|
||||||
return {
|
return {
|
||||||
$match: {
|
$match: {
|
||||||
$expr: {
|
$and: defaultMatches.concat({
|
||||||
$in: ['$_id', '$$localAlias'],
|
$expr: {
|
||||||
},
|
$in: ['$_id', '$$localAlias'],
|
||||||
|
},
|
||||||
|
}),
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@ -398,18 +420,22 @@ const buildLookupMatch = ({ assoc }) => {
|
|||||||
if (assoc.dominant === true) {
|
if (assoc.dominant === true) {
|
||||||
return {
|
return {
|
||||||
$match: {
|
$match: {
|
||||||
$expr: {
|
$and: defaultMatches.concat({
|
||||||
$in: ['$_id', '$$localAlias'],
|
$expr: {
|
||||||
},
|
$in: ['$_id', '$$localAlias'],
|
||||||
|
},
|
||||||
|
}),
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
$match: {
|
$match: {
|
||||||
$expr: {
|
$and: defaultMatches.concat({
|
||||||
$in: ['$$localId', `$${assoc.via}`],
|
$expr: {
|
||||||
},
|
$in: ['$$localId', `$${assoc.via}`],
|
||||||
|
},
|
||||||
|
}),
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@ -422,10 +448,10 @@ const buildLookupMatch = ({ assoc }) => {
|
|||||||
{
|
{
|
||||||
$match: {
|
$match: {
|
||||||
$expr: {
|
$expr: {
|
||||||
$and: [
|
$and: defaultMatches.concat(
|
||||||
{ $eq: [`$${assoc.via}.ref`, '$$localId'] },
|
{ $eq: [`$${assoc.via}.ref`, '$$localId'] },
|
||||||
{ $eq: [`$${assoc.via}.${assoc.filter}`, assoc.alias] },
|
{ $eq: [`$${assoc.via}.${assoc.filter}`, assoc.alias] }
|
||||||
],
|
),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
Loading…
x
Reference in New Issue
Block a user