mirror of
https://github.com/strapi/strapi.git
synced 2025-10-28 16:39:37 +00:00
refactor with groupby
This commit is contained in:
parent
a658c6cc0a
commit
aa53790bd5
@ -1,6 +1,5 @@
|
|||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
const _ = require('lodash');
|
|
||||||
const {
|
const {
|
||||||
isUndefined,
|
isUndefined,
|
||||||
castArray,
|
castArray,
|
||||||
@ -13,6 +12,10 @@ const {
|
|||||||
isEmpty,
|
isEmpty,
|
||||||
isArray,
|
isArray,
|
||||||
isNull,
|
isNull,
|
||||||
|
groupBy,
|
||||||
|
pipe,
|
||||||
|
mapValues,
|
||||||
|
map,
|
||||||
} = require('lodash/fp');
|
} = require('lodash/fp');
|
||||||
const types = require('./types');
|
const types = require('./types');
|
||||||
const { createField } = require('./fields');
|
const { createField } = require('./fields');
|
||||||
@ -416,25 +419,37 @@ const createEntityManager = (db) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// delete previous relations
|
// delete previous relations
|
||||||
const typeAndFieldIdsMap = {};
|
const morphOneRows = rows.filter((row) => {
|
||||||
|
const relatedType = row[typeColumn.name];
|
||||||
|
const field = row.field;
|
||||||
|
|
||||||
for (const { field, related_type: relatedType, related_id: relatedId } of rows) {
|
const targetAttribute = db.metadata.get(relatedType).attributes[field];
|
||||||
if (!relatedType) continue; // if !relatedType then it's a component. No need to handle that case
|
|
||||||
|
|
||||||
const isMorphOne =
|
// ensure targeted field is the right one + check if it is a morphOne
|
||||||
db.metadata.get(relatedType).attributes[field].relation === 'morphOne';
|
return (
|
||||||
if (isMorphOne) {
|
targetAttribute?.target === uid &&
|
||||||
const key = `${relatedType}+${field}`;
|
targetAttribute?.morphBy === attributeName &&
|
||||||
typeAndFieldIdsMap[key] = typeAndFieldIdsMap[key] || [];
|
targetAttribute?.relation === 'morphOne'
|
||||||
typeAndFieldIdsMap[key].push(relatedId);
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
const groupByType = groupBy(typeColumn.name);
|
||||||
|
const groupByField = groupBy('field');
|
||||||
|
|
||||||
|
const typeAndFieldIdsGrouped = pipe(groupByType, mapValues(groupByField))(morphOneRows);
|
||||||
|
|
||||||
|
const orWhere = [];
|
||||||
|
|
||||||
|
for (const [type, v] of Object.entries(typeAndFieldIdsGrouped)) {
|
||||||
|
for (const [field, arr] of Object.entries(v)) {
|
||||||
|
orWhere.push({
|
||||||
|
[typeColumn.name]: type,
|
||||||
|
field,
|
||||||
|
[idColumn.name]: { $in: map(idColumn.name, arr) },
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const orWhere = _.map(typeAndFieldIdsMap, (ids, typeAndField) => {
|
|
||||||
const [type, field] = typeAndField.split('+');
|
|
||||||
return { related_type: type, field, related_id: { $in: ids } };
|
|
||||||
});
|
|
||||||
|
|
||||||
if (!isEmpty(orWhere)) {
|
if (!isEmpty(orWhere)) {
|
||||||
await this.createQueryBuilder(joinTable.name)
|
await this.createQueryBuilder(joinTable.name)
|
||||||
.delete()
|
.delete()
|
||||||
@ -624,20 +639,42 @@ const createEntityManager = (db) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// delete previous relations
|
// delete previous relations
|
||||||
const where = { $or: [] };
|
const morphOneRows = rows.filter((row) => {
|
||||||
|
const relatedType = row[typeColumn.name];
|
||||||
|
const field = row.field;
|
||||||
|
|
||||||
for (const { field, related_type: relatedType, related_id: relatedId } of rows) {
|
const targetAttribute = db.metadata.get(relatedType).attributes[field];
|
||||||
if (!relatedType) continue; // if !relatedType then it's a component. No need to handle that case
|
|
||||||
|
|
||||||
const isMorphOne =
|
// ensure targeted field is the right one + check if it is a morphOne
|
||||||
db.metadata.get(relatedType).attributes[field].relation === 'morphOne';
|
return (
|
||||||
if (isMorphOne) {
|
targetAttribute?.target === uid &&
|
||||||
where.$or.push({ related_type: relatedType, field, related_id: relatedId });
|
targetAttribute?.morphBy === attributeName &&
|
||||||
|
targetAttribute?.relation === 'morphOne'
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
const groupByType = groupBy(typeColumn.name);
|
||||||
|
const groupByField = groupBy('field');
|
||||||
|
|
||||||
|
const typeAndFieldIdsGrouped = pipe(groupByType, mapValues(groupByField))(morphOneRows);
|
||||||
|
|
||||||
|
const orWhere = [];
|
||||||
|
|
||||||
|
for (const [type, v] of Object.entries(typeAndFieldIdsGrouped)) {
|
||||||
|
for (const [field, arr] of Object.entries(v)) {
|
||||||
|
orWhere.push({
|
||||||
|
[typeColumn.name]: type,
|
||||||
|
field,
|
||||||
|
[idColumn.name]: { $in: map(idColumn.name, arr) },
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!isEmpty(where.$or)) {
|
if (!isEmpty(orWhere)) {
|
||||||
await this.createQueryBuilder(joinTable.name).delete().where(where).execute();
|
await this.createQueryBuilder(joinTable.name)
|
||||||
|
.delete()
|
||||||
|
.where({ $or: orWhere })
|
||||||
|
.execute();
|
||||||
}
|
}
|
||||||
|
|
||||||
await this.createQueryBuilder(joinTable.name).insert(rows).execute();
|
await this.createQueryBuilder(joinTable.name).insert(rows).execute();
|
||||||
|
|||||||
@ -119,7 +119,7 @@ const applyPopulate = async (results, populate, ctx) => {
|
|||||||
return results;
|
return results;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (const key in populate) {
|
for (const key of Object.keys(populate)) {
|
||||||
const attribute = meta.attributes[key];
|
const attribute = meta.attributes[key];
|
||||||
const targetMeta = db.metadata.get(attribute.target);
|
const targetMeta = db.metadata.get(attribute.target);
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user