Skip to content

Commit

Permalink
Fix bug loopbackio#1795 Count issues related models
Browse files Browse the repository at this point in the history
  • Loading branch information
regevbr committed Nov 30, 2019
1 parent 9fe3858 commit 418d09e
Show file tree
Hide file tree
Showing 2 changed files with 399 additions and 79 deletions.
143 changes: 64 additions & 79 deletions lib/scope.js
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ ScopeDefinition.prototype.related = function(receiver, scopeParams, condOrRefres
actualRefresh;
if (refreshIsNeeded) {
// It either doesn't hit the cache or refresh is required
const params = mergeQuery(actualCond, scopeParams, {nestedInclude: true});
let params = mergeQuery(actualCond, scopeParams, {nestedInclude: true});
const targetModel = this.targetModel(receiver);

// If there is a through model
Expand All @@ -100,64 +100,39 @@ ScopeDefinition.prototype.related = function(receiver, scopeParams, condOrRefres
const scopeOnRelatedModel = params.collect &&
params.include.scope !== null &&
typeof params.include.scope === 'object';
let filter, queryRelated;
let filter, queryRelated, keyFrom, relatedModel, IdKey;
if (scopeOnRelatedModel) {
filter = params.include;
// The filter applied on relatedModel
queryRelated = filter.scope;
delete params.include.scope;
delete params.include;
relatedModel = targetModel.relations[filter.relation].modelTo;
IdKey = idName(relatedModel);
keyFrom = targetModel.relations[filter.relation].keyFrom || IdKey;
params.fields = [keyFrom];
if (queryRelated && queryRelated.where && queryRelated.where[IdKey]) {
params = mergeQuery(params, {
where: {
[keyFrom]: queryRelated.where [IdKey],
},
});
}
}

targetModel.find(params, options, function(err, data) {
targetModel.find(params, options, function(err, findData) {
if (!err && saveOnCache) {
defineCachedRelations(self);
self.__cachedRelations[name] = data;
self.__cachedRelations[name] = findData;
}

if (scopeOnRelatedModel === true) {
const relatedModel = targetModel.relations[filter.relation].modelTo;
const IdKey = idName(relatedModel);

// return {inq: [1,2,3]}}
const smartMerge = function(idCollection, qWhere) {
if (!qWhere[IdKey]) return idCollection;
let merged = {};

const idsA = idCollection.inq;
const idsB = qWhere[IdKey].inq ? qWhere[IdKey].inq : [qWhere[IdKey]];

const intersect = _.intersectionWith(idsA, idsB, _.isEqual);
if (intersect.length === 1) merged = intersect[0];
if (intersect.length > 1) merged = {inq: intersect};

return merged;
};

if (queryRelated.where !== undefined) {
// Merge queryRelated filter and targetId filter
const IdKeyCondition = {};
IdKeyCondition[IdKey] = smartMerge(collectTargetIds(data, IdKey),
queryRelated.where);

// if the id in filter doesn't exist after the merge,
// return empty result
if (_.isObject(IdKeyCondition[IdKey]) && _.isEmpty(IdKeyCondition[IdKey])) return cb(null, []);

const mergedWhere = {
and: [
IdKeyCondition,
_.omit(queryRelated.where, IdKey),
],
};
queryRelated.where = mergedWhere;
} else {
queryRelated.where = {};
queryRelated.where[IdKey] = collectTargetIds(data, IdKey);
const smartMergeSuccessful = smartMergeRelatedModelQuery(findData, queryRelated, keyFrom, IdKey);
if (!smartMergeSuccessful) {
return cb(null, []);
}

relatedModel.find(queryRelated, options, cb);
} else {
cb(err, data);
cb(err, findData);
}
});
} else {
Expand Down Expand Up @@ -298,6 +273,16 @@ function defineScope(cls, targetClass, name, params, methods, options) {
options = {};
}
options = options || {};
// Check if there is a through model
// see https://github.com/strongloop/loopback/issues/1076
if (f._scope.collect &&
condOrRefresh !== null && typeof condOrRefresh === 'object') {
f._scope.include = {
relation: f._scope.collect,
scope: condOrRefresh,
};
condOrRefresh = {};
}
return definition.related(self, f._scope, condOrRefresh, options, cb);
};

Expand Down Expand Up @@ -679,46 +664,46 @@ function defineScope(cls, targetClass, name, params, methods, options) {
});
}

function smartMergeRelatedModelQuery(findData, queryRelated, keyFrom, IdKey) {
const smartMerge = function(idCollection, qWhere) {
if (!qWhere[IdKey]) return idCollection;
let merged = {};
return definition;
}

const idsA = idCollection.inq;
const idsB = qWhere[IdKey].inq ? qWhere[IdKey].inq : [qWhere[IdKey]];
function smartMergeRelatedModelQuery(findData, queryRelated, keyFrom, IdKey) {
const smartMerge = function(idCollection, qWhere) {
if (!qWhere[IdKey]) return idCollection;
let merged = {};

const intersect = _.intersectionWith(idsA, idsB, _.isEqual);
if (intersect.length === 1) merged = intersect[0];
if (intersect.length > 1) merged = {inq: intersect};
const idsA = idCollection.inq;
const idsB = qWhere[IdKey].inq ? qWhere[IdKey].inq : [qWhere[IdKey]];

return merged;
};
const intersect = _.intersectionWith(idsA, idsB, _.isEqual);
if (intersect.length === 1) merged = intersect[0];
if (intersect.length > 1) merged = {inq: intersect};

if (queryRelated.where !== undefined) {
// Merge queryRelated filter and targetId filter
const IdKeyCondition = {};
IdKeyCondition[IdKey] = smartMerge(collectTargetIds(findData, keyFrom),
queryRelated.where);
return merged;
};

// if the id in filter doesn't exist after the merge,
// return empty result
if (_.isObject(IdKeyCondition[IdKey]) && _.isEmpty(IdKeyCondition[IdKey])) {
return false;
}
if (queryRelated.where !== undefined) {
// Merge queryRelated filter and targetId filter
const IdKeyCondition = {};
IdKeyCondition[IdKey] = smartMerge(collectTargetIds(findData, keyFrom),
queryRelated.where);

const mergedWhere = {
and: [
IdKeyCondition,
_.omit(queryRelated.where, IdKey),
],
};
queryRelated.where = mergedWhere;
} else {
queryRelated.where = {};
queryRelated.where[IdKey] = collectTargetIds(findData, keyFrom);
// if the id in filter doesn't exist after the merge,
// return empty result
if (_.isObject(IdKeyCondition[IdKey]) && _.isEmpty(IdKeyCondition[IdKey])) {
return false;
}
return true;
}

return definition;
const mergedWhere = {
and: [
IdKeyCondition,
_.omit(queryRelated.where, IdKey),
],
};
queryRelated.where = mergedWhere;
} else {
queryRelated.where = {};
queryRelated.where[IdKey] = collectTargetIds(findData, keyFrom);
}
return true;
}
Loading

0 comments on commit 418d09e

Please sign in to comment.