From 7a4c6ca2f9033dbc63f6f2a236182ecba4cfb9c2 Mon Sep 17 00:00:00 2001 From: Joost de Bruijn Date: Tue, 14 Nov 2017 20:22:48 +0100 Subject: [PATCH] Fix query for related models (#1522) --- lib/scope.js | 46 +++++++++++++++++++++++++----------------- test/relations.test.js | 23 +++++++++++++++++---- 2 files changed, 46 insertions(+), 23 deletions(-) diff --git a/lib/scope.js b/lib/scope.js index 68af1af6..4dc2f290 100644 --- a/lib/scope.js +++ b/lib/scope.js @@ -116,30 +116,38 @@ ScopeDefinition.prototype.related = function(receiver, scopeParams, condOrRefres var relatedModel = targetModel.relations[filter.relation].modelTo; var IdKey = idName(relatedModel); - var smartMerge = function(idCond, qWhere, idKey) { + // return {inq: [1,2,3]}} + var smartMerge = function(idCollection, qWhere) { + if (!qWhere[IdKey]) return idCollection; var merged = {}; - var idsA = idCond[idKey].inq; - var idsB = qWhere[idKey].inq ? qWhere[idKey].inq : [qWhere[idKey]]; + + var idsA = idCollection.inq; + var idsB = qWhere[IdKey].inq ? qWhere[IdKey].inq : [qWhere[IdKey]]; + var intersect = _.intersectionWith(idsA, idsB, _.isEqual); - if (intersect.length === 1) merged[idKey] = intersect[0]; - if (intersect.length > 1) merged[idKey] = {inq: intersect}; + if (intersect.length === 1) merged = intersect[0]; + if (intersect.length > 1) merged = {inq: intersect}; + return merged; }; - // Merge queryRelated filter and targetId filter - var buildWhere = function() { - var IdKeyCondition = {}; - IdKeyCondition[IdKey] = collectTargetIds(data, IdKey); - var mergedWhere = smartMerge(IdKeyCondition, queryRelated.where, IdKey); - return mergedWhere; - }; + if (queryRelated.where !== undefined) { - if (!queryRelated.where[IdKey]) { - // If it's null, don't bother calling smartMerge or model.find. - // Simply return an empty result to the client. - return cb(null, []); - } else { - queryRelated.where = buildWhere(); - } + // Merge queryRelated filter and targetId filter + var 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, []); + + var mergedWhere = { + and: [ + IdKeyCondition, + _.omit(queryRelated.where, IdKey), + ], + }; + queryRelated.where = mergedWhere; } else { queryRelated.where = {}; queryRelated.where[IdKey] = collectTargetIds(data, IdKey); diff --git a/test/relations.test.js b/test/relations.test.js index 301143f2..44a5b005 100644 --- a/test/relations.test.js +++ b/test/relations.test.js @@ -820,12 +820,13 @@ describe('relations', function() { done(); }); }); - it('returns empty result when filtering with wrong id key', function(done) { - var wrongWhereFilter = {where: {wrongIdKey: samplePatientId}}; - physician.patients(wrongWhereFilter, function(err, ch) { + it('returns patient where name equal to samplePatient name', function(done) { + var whereFilter = {where: {name: 'a'}}; + physician.patients(whereFilter, function(err, ch) { if (err) return done(err); should.exist(ch); - ch.should.have.lengthOf(0); + ch.should.have.lengthOf(1); + ch[0].name.should.eql('a'); done(); }); }); @@ -853,6 +854,20 @@ describe('relations', function() { }); }); }); + it('returns empty result when patientId does not belongs to physician', function(done) { + Patient.create({name: 'x'}, function(err, p) { + if (err) return done(err); + should.exist(p); + + var wrongWhereFilter = {where: {id: p.id}}; + physician.patients(wrongWhereFilter, function(err, ch) { + if (err) return done(err); + should.exist(ch); + ch.should.have.lengthOf(0); + done(); + }); + }); + }); }); context('findById with filter include', function() { it('returns patient where id equal to \'samplePatientId\'' +