Fix the target id resolution
This commit is contained in:
parent
f9bd1544f9
commit
b5b7bab096
|
@ -139,19 +139,19 @@ Inclusion.normalizeInclude = normalizeInclude;
|
||||||
* `User.include(users, ['posts', 'passports'], function() {});`
|
* `User.include(users, ['posts', 'passports'], function() {});`
|
||||||
*
|
*
|
||||||
* Load all passports owner (users), and all posts of each owner loaded:
|
* Load all passports owner (users), and all posts of each owner loaded:
|
||||||
*```Passport.include(passports, {owner: 'posts'}, function() {});
|
*```Passport.include(passports, {owner: 'posts'}, function() {});
|
||||||
*``` Passport.include(passports, {owner: ['posts', 'passports']});
|
*``` Passport.include(passports, {owner: ['posts', 'passports']});
|
||||||
*``` Passport.include(passports, {owner: [{posts: 'images'}, 'passports']});
|
*``` Passport.include(passports, {owner: [{posts: 'images'}, 'passports']});
|
||||||
*
|
*
|
||||||
* @param {Array} objects Array of instances
|
* @param {Array} objects Array of instances
|
||||||
* @param {String|Object|Array} include Which relations to load.
|
* @param {String|Object|Array} include Which relations to load.
|
||||||
* @param {Function} cb Callback called when relations are loaded
|
* @param {Function} cb Callback called when relations are loaded
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
Inclusion.include = function (objects, include, cb) {
|
Inclusion.include = function (objects, include, cb) {
|
||||||
debug('include', include);
|
debug('include', include);
|
||||||
var self = this;
|
var self = this;
|
||||||
|
|
||||||
if (!include || (Array.isArray(include) && include.length === 0) ||
|
if (!include || (Array.isArray(include) && include.length === 0) ||
|
||||||
(isPlainObject(include) && Object.keys(include).length === 0)) {
|
(isPlainObject(include) && Object.keys(include).length === 0)) {
|
||||||
// The objects are empty
|
// The objects are empty
|
||||||
|
@ -161,7 +161,7 @@ Inclusion.include = function (objects, include, cb) {
|
||||||
}
|
}
|
||||||
|
|
||||||
include = normalizeInclude(include);
|
include = normalizeInclude(include);
|
||||||
|
|
||||||
async.each(include, function(item, callback) {
|
async.each(include, function(item, callback) {
|
||||||
processIncludeItem(objects, item, callback);
|
processIncludeItem(objects, item, callback);
|
||||||
}, function(err) {
|
}, function(err) {
|
||||||
|
@ -170,10 +170,10 @@ Inclusion.include = function (objects, include, cb) {
|
||||||
|
|
||||||
function processIncludeItem(objs, include, cb) {
|
function processIncludeItem(objs, include, cb) {
|
||||||
var relations = self.relations;
|
var relations = self.relations;
|
||||||
|
|
||||||
var relationName;
|
var relationName;
|
||||||
var subInclude = null, scope = null;
|
var subInclude = null, scope = null;
|
||||||
|
|
||||||
if (isPlainObject(include)) {
|
if (isPlainObject(include)) {
|
||||||
relationName = Object.keys(include)[0];
|
relationName = Object.keys(include)[0];
|
||||||
if (include[relationName] instanceof IncludeScope) {
|
if (include[relationName] instanceof IncludeScope) {
|
||||||
|
@ -191,7 +191,7 @@ Inclusion.include = function (objects, include, cb) {
|
||||||
relationName = include;
|
relationName = include;
|
||||||
subInclude = null;
|
subInclude = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
var relation = relations[relationName];
|
var relation = relations[relationName];
|
||||||
if (!relation) {
|
if (!relation) {
|
||||||
cb(new Error('Relation "' + relationName + '" is not defined for '
|
cb(new Error('Relation "' + relationName + '" is not defined for '
|
||||||
|
@ -283,7 +283,6 @@ Inclusion.include = function (objects, include, cb) {
|
||||||
* @param callback
|
* @param callback
|
||||||
*/
|
*/
|
||||||
function includeHasManyThrough(callback) {
|
function includeHasManyThrough(callback) {
|
||||||
var debug = require('debug')('loopback:include:includeHasManyThrough');
|
|
||||||
var sourceIds = [];
|
var sourceIds = [];
|
||||||
//Map for Indexing objects by their id for faster retrieval
|
//Map for Indexing objects by their id for faster retrieval
|
||||||
var objIdMap = {};
|
var objIdMap = {};
|
||||||
|
@ -317,7 +316,7 @@ Inclusion.include = function (objects, include, cb) {
|
||||||
/**
|
/**
|
||||||
* 1st DB Call of 2 step process. Get through model objects first
|
* 1st DB Call of 2 step process. Get through model objects first
|
||||||
*/
|
*/
|
||||||
relation.modelThrough.all(throughFilter, throughFetchHandler);
|
relation.modelThrough.find(throughFilter, throughFetchHandler);
|
||||||
/**
|
/**
|
||||||
* Handle the results of Through model objects and fetch the modelTo items
|
* Handle the results of Through model objects and fetch the modelTo items
|
||||||
* @param err
|
* @param err
|
||||||
|
@ -362,8 +361,11 @@ Inclusion.include = function (objects, include, cb) {
|
||||||
/**
|
/**
|
||||||
* 2nd DB Call of 2 step process. Get modelTo (target) objects
|
* 2nd DB Call of 2 step process. Get modelTo (target) objects
|
||||||
*/
|
*/
|
||||||
relation.modelTo.all(filter, targetsFetchHandler);
|
relation.modelTo.find(filter, targetsFetchHandler);
|
||||||
function targetsFetchHandler(err, targets) {
|
function targetsFetchHandler(err, targets) {
|
||||||
|
if (err) {
|
||||||
|
return callback(err);
|
||||||
|
}
|
||||||
var tasks = [];
|
var tasks = [];
|
||||||
//simultaneously process subIncludes. Call it first as it is an async
|
//simultaneously process subIncludes. Call it first as it is an async
|
||||||
//process.
|
//process.
|
||||||
|
@ -396,7 +398,6 @@ Inclusion.include = function (objects, include, cb) {
|
||||||
* @param callback
|
* @param callback
|
||||||
*/
|
*/
|
||||||
function includeReferencesMany(callback) {
|
function includeReferencesMany(callback) {
|
||||||
var debug = require('debug')('loopback:include:includeReferencesMany');
|
|
||||||
var allTargetIds = [];
|
var allTargetIds = [];
|
||||||
//Map for Indexing objects by their id for faster retrieval
|
//Map for Indexing objects by their id for faster retrieval
|
||||||
var targetObjsMap = {};
|
var targetObjsMap = {};
|
||||||
|
@ -406,6 +407,11 @@ Inclusion.include = function (objects, include, cb) {
|
||||||
// use modelFrom.keyFrom in where filter later
|
// use modelFrom.keyFrom in where filter later
|
||||||
var targetIds = obj[relation.keyFrom];
|
var targetIds = obj[relation.keyFrom];
|
||||||
if (targetIds) {
|
if (targetIds) {
|
||||||
|
if (typeof targetIds === 'string') {
|
||||||
|
// For relational DBs, the array is stored as stringified json
|
||||||
|
// Please note obj is a plain object at this point
|
||||||
|
targetIds = JSON.parse(targetIds);
|
||||||
|
}
|
||||||
//referencesMany has multiple targetIds per obj. We need to concat
|
//referencesMany has multiple targetIds per obj. We need to concat
|
||||||
// them into allTargetIds before DB Call
|
// them into allTargetIds before DB Call
|
||||||
allTargetIds = allTargetIds.concat(targetIds);
|
allTargetIds = allTargetIds.concat(targetIds);
|
||||||
|
@ -424,10 +430,11 @@ Inclusion.include = function (objects, include, cb) {
|
||||||
filter.where[relation.keyTo] = {
|
filter.where[relation.keyTo] = {
|
||||||
inq: allTargetIds
|
inq: allTargetIds
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Make the DB Call, fetch all target objects
|
* Make the DB Call, fetch all target objects
|
||||||
*/
|
*/
|
||||||
relation.modelTo.all(filter, targetFetchHandler);
|
relation.modelTo.find(filter, targetFetchHandler);
|
||||||
/**
|
/**
|
||||||
* Handle the fetched target objects
|
* Handle the fetched target objects
|
||||||
* @param err
|
* @param err
|
||||||
|
@ -468,7 +475,6 @@ Inclusion.include = function (objects, include, cb) {
|
||||||
* @param callback
|
* @param callback
|
||||||
*/
|
*/
|
||||||
function includeHasMany(callback) {
|
function includeHasMany(callback) {
|
||||||
var debug = require('debug')('loopback:include:includeHasMany');
|
|
||||||
var sourceIds = [];
|
var sourceIds = [];
|
||||||
//Map for Indexing objects by their id for faster retrieval
|
//Map for Indexing objects by their id for faster retrieval
|
||||||
var objIdMap = {};
|
var objIdMap = {};
|
||||||
|
@ -488,7 +494,7 @@ Inclusion.include = function (objects, include, cb) {
|
||||||
filter.where[relation.keyTo] = {
|
filter.where[relation.keyTo] = {
|
||||||
inq: sourceIds
|
inq: sourceIds
|
||||||
};
|
};
|
||||||
relation.modelTo.all(filter, targetFetchHandler);
|
relation.modelTo.find(filter, targetFetchHandler);
|
||||||
/**
|
/**
|
||||||
* Process fetched related objects
|
* Process fetched related objects
|
||||||
* @param err
|
* @param err
|
||||||
|
@ -526,7 +532,6 @@ Inclusion.include = function (objects, include, cb) {
|
||||||
* @param callback
|
* @param callback
|
||||||
*/
|
*/
|
||||||
function includePolymorphic(callback) {
|
function includePolymorphic(callback) {
|
||||||
var debug = require('debug')('loopback:include:includePolymorphic');
|
|
||||||
var targetIdsByType = {};
|
var targetIdsByType = {};
|
||||||
//Map for Indexing objects by their type and targetId for faster retrieval
|
//Map for Indexing objects by their type and targetId for faster retrieval
|
||||||
var targetObjMapByType = {};
|
var targetObjMapByType = {};
|
||||||
|
@ -562,6 +567,7 @@ Inclusion.include = function (objects, include, cb) {
|
||||||
function processPolymorphicType(modelType, callback) {
|
function processPolymorphicType(modelType, callback) {
|
||||||
var typeFilter = {where: {}};
|
var typeFilter = {where: {}};
|
||||||
utils.mergeQuery(typeFilter, filter);
|
utils.mergeQuery(typeFilter, filter);
|
||||||
|
var targetIds = targetIdsByType[modelType];
|
||||||
typeFilter.where[relation.keyTo] = {
|
typeFilter.where[relation.keyTo] = {
|
||||||
inq: targetIds
|
inq: targetIds
|
||||||
};
|
};
|
||||||
|
@ -573,7 +579,7 @@ Inclusion.include = function (objects, include, cb) {
|
||||||
' specified but no model exists with such name'));
|
' specified but no model exists with such name'));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
Model.all(typeFilter, targetFetchHandler);
|
Model.find(typeFilter, targetFetchHandler);
|
||||||
/**
|
/**
|
||||||
* Process fetched related objects
|
* Process fetched related objects
|
||||||
* @param err
|
* @param err
|
||||||
|
@ -616,7 +622,6 @@ Inclusion.include = function (objects, include, cb) {
|
||||||
* @param callback
|
* @param callback
|
||||||
*/
|
*/
|
||||||
function includeOneToOne(callback) {
|
function includeOneToOne(callback) {
|
||||||
var debug = require('debug')('loopback:include:includeOneToOne');
|
|
||||||
var targetIds = [];
|
var targetIds = [];
|
||||||
var objTargetIdMap = {};
|
var objTargetIdMap = {};
|
||||||
for (var i = 0; i < objs.length; i++) {
|
for (var i = 0; i < objs.length; i++) {
|
||||||
|
@ -642,7 +647,7 @@ Inclusion.include = function (objects, include, cb) {
|
||||||
filter.where[relation.keyTo] = {
|
filter.where[relation.keyTo] = {
|
||||||
inq: targetIds
|
inq: targetIds
|
||||||
};
|
};
|
||||||
relation.modelTo.all(filter, targetFetchHandler);
|
relation.modelTo.find(filter, targetFetchHandler);
|
||||||
/**
|
/**
|
||||||
* Process fetched related objects
|
* Process fetched related objects
|
||||||
* @param err
|
* @param err
|
||||||
|
@ -741,11 +746,11 @@ Inclusion.include = function (objects, include, cb) {
|
||||||
//If related objects are not cached by include Handlers, directly call
|
//If related objects are not cached by include Handlers, directly call
|
||||||
//related accessor function even though it is not very efficient
|
//related accessor function even though it is not very efficient
|
||||||
var related; // relation accessor function
|
var related; // relation accessor function
|
||||||
|
|
||||||
if ((relation.multiple || relation.type === 'belongsTo') && scope) {
|
if ((relation.multiple || relation.type === 'belongsTo') && scope) {
|
||||||
var includeScope = {};
|
var includeScope = {};
|
||||||
var filter = scope.conditions();
|
var filter = scope.conditions();
|
||||||
|
|
||||||
// make sure not to miss any fields for sub includes
|
// make sure not to miss any fields for sub includes
|
||||||
if (filter.fields && Array.isArray(subInclude) && relation.modelTo.relations) {
|
if (filter.fields && Array.isArray(subInclude) && relation.modelTo.relations) {
|
||||||
includeScope.fields = [];
|
includeScope.fields = [];
|
||||||
|
@ -756,22 +761,22 @@ Inclusion.include = function (objects, include, cb) {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
utils.mergeQuery(filter, includeScope, {fields: false});
|
utils.mergeQuery(filter, includeScope, {fields: false});
|
||||||
|
|
||||||
related = inst[relationName].bind(inst, filter);
|
related = inst[relationName].bind(inst, filter);
|
||||||
} else {
|
} else {
|
||||||
related = inst[relationName].bind(inst);
|
related = inst[relationName].bind(inst);
|
||||||
}
|
}
|
||||||
|
|
||||||
related(function (err, result) {
|
related(function (err, result) {
|
||||||
if (err) {
|
if (err) {
|
||||||
return callback(err);
|
return callback(err);
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
defineCachedRelations(obj);
|
defineCachedRelations(obj);
|
||||||
obj.__cachedRelations[relationName] = result;
|
obj.__cachedRelations[relationName] = result;
|
||||||
|
|
||||||
return setIncludeData(result, callback);
|
return setIncludeData(result, callback);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
Loading…
Reference in New Issue