Skip to content

Commit 2cf6dba

Browse files
committed
Fix loopbackio#1795 - Count issue with related models using though model
1 parent baf872f commit 2cf6dba

File tree

2 files changed

+71
-1
lines changed

2 files changed

+71
-1
lines changed

lib/scope.js

+40-1
Original file line numberDiff line numberDiff line change
@@ -500,10 +500,49 @@ function defineScope(cls, targetClass, name, params, methods, options) {
500500
options = {};
501501
}
502502
options = options || {};
503+
// If there is a through model
504+
// run another query to apply filter on relatedModel(targetModel)
505+
// see github.com/strongloop/loopback-datasource-juggler/issues/1795
506+
let scopeOnRelatedModel = false;
507+
let queryRelated;
508+
if (this._scope && this._scope.collect &&
509+
filter && filter.where !== null && typeof filter.where === 'object') {
510+
queryRelated = {
511+
relation: this._scope.collect,
512+
scope: filter,
513+
};
514+
filter = {};
515+
scopeOnRelatedModel = true;
516+
}
503517
const targetModel = definition.targetModel(this._receiver);
504518
const scoped = (this._scope && this._scope.where) || {};
505519
filter = mergeQuery({where: scoped}, filter || {});
506-
return targetModel.findOne(filter, options, cb);
520+
if (!scopeOnRelatedModel) {
521+
return targetModel.findOne(filter, options, cb);
522+
}
523+
return targetModel.find(filter, options, function(err, data) {
524+
const relatedModel = targetModel.relations[queryRelated.relation].modelTo;
525+
const keyFrom = targetModel.relations[queryRelated.relation].keyFrom;
526+
const IdKey = idName(relatedModel);
527+
528+
// Merge queryRelated filter and targetId filter
529+
const buildWhere = function() {
530+
return {
531+
and: [
532+
{
533+
[IdKey]: collectTargetIds(data, keyFrom || IdKey),
534+
},
535+
queryRelated.scope.where],
536+
};
537+
};
538+
if (queryRelated.scope.where !== undefined) {
539+
queryRelated.scope.where = buildWhere();
540+
} else {
541+
queryRelated.scope.where = {};
542+
queryRelated.scope.where[IdKey] = collectTargetIds(data, keyFrom || IdKey);
543+
}
544+
return relatedModel.findOne(queryRelated.scope, options, cb);
545+
});
507546
}
508547

509548
function count(where, options, cb) {

test/relations.test.js

+31
Original file line numberDiff line numberDiff line change
@@ -633,6 +633,37 @@ describe('relations', function() {
633633
}
634634
});
635635

636+
it('should find one scoped record with promises based on related model properties', function(done) {
637+
let id;
638+
Physician.create()
639+
.then(function(physician) {
640+
return physician.patients.create({name: 'a'})
641+
.then(function(ch) {
642+
id = ch.id;
643+
return physician.patients.create({name: 'z'});
644+
})
645+
.then(function() {
646+
return physician.patients.create({name: 'c'});
647+
})
648+
.then(function() {
649+
return verify(physician);
650+
});
651+
}).catch(done);
652+
653+
function verify(physician) {
654+
return physician.patients.findOne({
655+
where: {
656+
name: 'a',
657+
},
658+
}, function(err, patient) {
659+
if (err) return done(err);
660+
should.exist(patient);
661+
patient.name.should.equal('a');
662+
done();
663+
});
664+
}
665+
});
666+
636667
it('should build record on scope', function(done) {
637668
Physician.create(function(err, physician) {
638669
const patient = physician.patients.build();

0 commit comments

Comments
 (0)