Skip to content

Commit

Permalink
Fix loopbackio#1795 - Count issue with related models using though model
Browse files Browse the repository at this point in the history
  • Loading branch information
regevbr committed Nov 30, 2019
1 parent ebdc4ae commit c2f1b7b
Showing 1 changed file with 48 additions and 32 deletions.
80 changes: 48 additions & 32 deletions lib/scope.js
Original file line number Diff line number Diff line change
Expand Up @@ -431,11 +431,16 @@ function defineScope(cls, targetClass, name, params, methods, options) {
options = {};
}
options = options || {};
const targetModel = definition.targetModel(this._receiver);
// If there is a through model
// run another query to apply filter on relatedModel(targetModel)
// see github.com/strongloop/loopback-datasource-juggler/issues/1795
let scopeOnRelatedModel = false;
let queryRelated;
let keyFrom;
let relatedModel;
let IdKey;
let fieldsRelated;
if (this._scope && this._scope.collect &&
where !== null && typeof where === 'object') {
queryRelated = {
Expand All @@ -446,24 +451,23 @@ function defineScope(cls, targetClass, name, params, methods, options) {
};
where = {};
scopeOnRelatedModel = true;
relatedModel = targetModel.relations[queryRelated.relation].modelTo;
IdKey = idName(relatedModel);
keyFrom = targetModel.relations[queryRelated.relation].keyFrom || IdKey;
fieldsRelated = [keyFrom];
}
const targetModel = definition.targetModel(this._receiver);
const scoped = (this._scope && this._scope.where) || {};
const filter = mergeQuery({where: scoped}, {where: where || {}});
const filter = mergeQuery({where: scoped}, {where: where || {}, fields: fieldsRelated});
if (!scopeOnRelatedModel) {
return targetModel.destroyAll(filter.where, options, cb);
}
return targetModel.find(filter, options, function(err, findData) {
const relatedModel = targetModel.relations[queryRelated.relation].modelTo;
const keyFrom = targetModel.relations[queryRelated.relation].keyFrom;
const IdKey = idName(relatedModel);

// Merge queryRelated filter and targetId filter
const buildWhere = function() {
return {
and: [
{
[IdKey]: collectTargetIds(findData, keyFrom || IdKey),
[IdKey]: collectTargetIds(findData, keyFrom),
},
queryRelated.scope.where],
};
Expand All @@ -472,7 +476,7 @@ function defineScope(cls, targetClass, name, params, methods, options) {
queryRelated.scope.where = buildWhere();
} else {
queryRelated.scope.where = {};
queryRelated.scope.where[IdKey] = collectTargetIds(findData, keyFrom || IdKey);
queryRelated.scope.where[IdKey] = collectTargetIds(findData, keyFrom);
}
return relatedModel.destroyAll(queryRelated.scope.where, options, cb);
});
Expand All @@ -492,11 +496,16 @@ function defineScope(cls, targetClass, name, params, methods, options) {
options = {};
}
options = options || {};
const targetModel = definition.targetModel(this._receiver);
// If there is a through model
// run another query to apply filter on relatedModel(targetModel)
// see github.com/strongloop/loopback-datasource-juggler/issues/1795
let scopeOnRelatedModel = false;
let queryRelated;
let keyFrom;
let relatedModel;
let IdKey;
let fieldsRelated;
if (this._scope && this._scope.collect &&
where !== null && typeof where === 'object') {
queryRelated = {
Expand All @@ -507,24 +516,23 @@ function defineScope(cls, targetClass, name, params, methods, options) {
};
where = {};
scopeOnRelatedModel = true;
relatedModel = targetModel.relations[queryRelated.relation].modelTo;
IdKey = idName(relatedModel);
keyFrom = targetModel.relations[queryRelated.relation].keyFrom || IdKey;
fieldsRelated = [keyFrom];
}
const targetModel = definition.targetModel(this._receiver);
const scoped = (this._scope && this._scope.where) || {};
const filter = mergeQuery({where: scoped}, {where: where || {}});
const filter = mergeQuery({where: scoped}, {where: where || {}, fields: fieldsRelated});
if (!scopeOnRelatedModel) {
return targetModel.updateAll(filter.where, data, options, cb);
}
return targetModel.find(filter, options, function(err, findData) {
const relatedModel = targetModel.relations[queryRelated.relation].modelTo;
const keyFrom = targetModel.relations[queryRelated.relation].keyFrom;
const IdKey = idName(relatedModel);

// Merge queryRelated filter and targetId filter
const buildWhere = function() {
return {
and: [
{
[IdKey]: collectTargetIds(findData, keyFrom || IdKey),
[IdKey]: collectTargetIds(findData, keyFrom),
},
queryRelated.scope.where],
};
Expand All @@ -533,7 +541,7 @@ function defineScope(cls, targetClass, name, params, methods, options) {
queryRelated.scope.where = buildWhere();
} else {
queryRelated.scope.where = {};
queryRelated.scope.where[IdKey] = collectTargetIds(findData, keyFrom || IdKey);
queryRelated.scope.where[IdKey] = collectTargetIds(findData, keyFrom);
}
return relatedModel.updateAll(queryRelated.scope.where, data, options, cb);
});
Expand Down Expand Up @@ -581,37 +589,41 @@ function defineScope(cls, targetClass, name, params, methods, options) {
options = {};
}
options = options || {};
const targetModel = definition.targetModel(this._receiver);
// If there is a through model
// run another query to apply filter on relatedModel(targetModel)
// see github.com/strongloop/loopback-datasource-juggler/issues/1795
let scopeOnRelatedModel = false;
let queryRelated;
let keyFrom;
let relatedModel;
let IdKey;
if (this._scope && this._scope.collect &&
filter && filter.where !== null && typeof filter.where === 'object') {
queryRelated = {
relation: this._scope.collect,
scope: filter,
};
filter = {};
scopeOnRelatedModel = true;
relatedModel = targetModel.relations[queryRelated.relation].modelTo;
IdKey = idName(relatedModel);
keyFrom = targetModel.relations[queryRelated.relation].keyFrom || IdKey;
filter = {
fields: [keyFrom],
};
}
const targetModel = definition.targetModel(this._receiver);
const scoped = (this._scope && this._scope.where) || {};
filter = mergeQuery({where: scoped}, filter || {});
if (!scopeOnRelatedModel) {
return targetModel.findOne(filter, options, cb);
}
return targetModel.find(filter, options, function(err, data) {
const relatedModel = targetModel.relations[queryRelated.relation].modelTo;
const keyFrom = targetModel.relations[queryRelated.relation].keyFrom;
const IdKey = idName(relatedModel);

// Merge queryRelated filter and targetId filter
const buildWhere = function() {
return {
and: [
{
[IdKey]: collectTargetIds(data, keyFrom || IdKey),
[IdKey]: collectTargetIds(data, keyFrom),
},
queryRelated.scope.where],
};
Expand All @@ -620,7 +632,7 @@ function defineScope(cls, targetClass, name, params, methods, options) {
queryRelated.scope.where = buildWhere();
} else {
queryRelated.scope.where = {};
queryRelated.scope.where[IdKey] = collectTargetIds(data, keyFrom || IdKey);
queryRelated.scope.where[IdKey] = collectTargetIds(data, keyFrom);
}
return relatedModel.findOne(queryRelated.scope, options, cb);
});
Expand All @@ -637,11 +649,16 @@ function defineScope(cls, targetClass, name, params, methods, options) {
options = {};
}
options = options || {};
const targetModel = definition.targetModel(this._receiver);
// If there is a through model
// run another query to apply filter on relatedModel(targetModel)
// see github.com/strongloop/loopback-datasource-juggler/issues/1795
let scopeOnRelatedModel = false;
let queryRelated;
let keyFrom;
let relatedModel;
let IdKey;
let fieldsRelated;
if (this._scope && this._scope.collect &&
where !== null && typeof where === 'object') {
queryRelated = {
Expand All @@ -652,24 +669,23 @@ function defineScope(cls, targetClass, name, params, methods, options) {
};
where = {};
scopeOnRelatedModel = true;
relatedModel = targetModel.relations[queryRelated.relation].modelTo;
IdKey = idName(relatedModel);
keyFrom = targetModel.relations[queryRelated.relation].keyFrom || IdKey;
fieldsRelated = [keyFrom];
}
const targetModel = definition.targetModel(this._receiver);
const scoped = (this._scope && this._scope.where) || {};
const filter = mergeQuery({where: scoped}, {where: where || {}});
const filter = mergeQuery({where: scoped}, {where: where || {}, fields: fieldsRelated});
if (!scopeOnRelatedModel) {
return targetModel.count(filter.where, options, cb);
}
return targetModel.find(filter, options, function(err, data) {
const relatedModel = targetModel.relations[queryRelated.relation].modelTo;
const keyFrom = targetModel.relations[queryRelated.relation].keyFrom;
const IdKey = idName(relatedModel);

// Merge queryRelated filter and targetId filter
const buildWhere = function() {
return {
and: [
{
[IdKey]: collectTargetIds(data, keyFrom || IdKey),
[IdKey]: collectTargetIds(data, keyFrom),
},
queryRelated.scope.where],
};
Expand All @@ -678,7 +694,7 @@ function defineScope(cls, targetClass, name, params, methods, options) {
queryRelated.scope.where = buildWhere();
} else {
queryRelated.scope.where = {};
queryRelated.scope.where[IdKey] = collectTargetIds(data, keyFrom || IdKey);
queryRelated.scope.where[IdKey] = collectTargetIds(data, keyFrom);
}
return relatedModel.count(queryRelated.scope.where, options, cb);
});
Expand Down

0 comments on commit c2f1b7b

Please sign in to comment.