I have a model Mat with HasOne relation Origin. I have local model LocalMat in the client.
Calling localMat.origin() causes Unknown "origin" id "undefined".
It seams that https://github.com/strongloop/loopback-datasource-juggler/blob/master/lib/relation-definition.js#L1432 is useing the model name 'localMat' to create the foreign key 'localMatId' which is incorrect.
This does not seem to affect hasMany, belongsTo relationships.
This sounds like a bug. I think we need to inherit the foreign key from the parent model. /cc @raymondfeng
@kraman have you run into this?
@BerkeleyTrue a potential workaround is to set the foreign key in your model-config.json.
@ritch Haven't run into this situation yet but I probably will soon or later.
@ritch Yes, this is what I have been doing in the mean time.
Any news on this one ? I think I have the same problem...
I have 2 models with a hasone relation :
In appointment.json :
...
"relations": {
"CustomFields": {
"type": "hasOne",
"model": "CustomField",
"foreignKey": "id_rdv"
}
},
...
When I try GET /Appointments/{id}/CustomFields here's the response :
{
"error": {
"name": "Error",
"status": 404,
"message": "Unknown \"SubscriberCustomField\" id \"undefined\".",
"statusCode": 404,
"code": "MODEL_NOT_FOUND",
"stack": "Error: Unknown \"SubscriberCustomField\" id \"undefined\".\n at convertNullToNotFoundError (/Users/airzebeth/Documents/Kaamelote/Work/wzagendasynchro/node_modules/loopback/lib/model.js:456:17)\n at invokeRestAfter (/Users/airzebeth/Documents/Kaamelote/Work/wzagendasynchro/node_modules/loopback/node_modules/strong-remoting/lib/rest-adapter.js:453:25)\n at /Users/airzebeth/Documents/Kaamelote/Work/wzagendasynchro/node_modules/loopback/node_modules/async/lib/async.js:607:21\n at /Users/airzebeth/Documents/Kaamelote/Work/wzagendasynchro/node_modules/loopback/node_modules/async/lib/async.js:246:17\n at iterate (/Users/airzebeth/Documents/Kaamelote/Work/wzagendasynchro/node_modules/loopback/node_modules/async/lib/async.js:146:13)\n at /Users/airzebeth/Documents/Kaamelote/Work/wzagendasynchro/node_modules/loopback/node_modules/async/lib/async.js:157:25\n at /Users/airzebeth/Documents/Kaamelote/Work/wzagendasynchro/node_modules/loopback/node_modules/async/lib/async.js:248:21\n at /Users/airzebeth/Documents/Kaamelote/Work/wzagendasynchro/node_modules/loopback/node_modules/async/lib/async.js:612:34\n at /Users/airzebeth/Documents/Kaamelote/Work/wzagendasynchro/node_modules/loopback/node_modules/strong-remoting/lib/remote-objects.js:685:7\n at execStack (/Users/airzebeth/Documents/Kaamelote/Work/wzagendasynchro/node_modules/loopback/node_modules/strong-remoting/lib/remote-objects.js:488:7)"
}
}
I didn't understand how to "set the foreign key in your model-config.json." Tried it but didn't make any difference. Could you please help I've hit a wall there...
Thanks in advance.
+1
+1
+1
fixed this on my fork yesterday
replace the includeOneToOne function in loopback-datasource-juggler with https://gist.github.com/BoLaMN/6590e8849d23f6373a177d5ccc42ef23
replaces the hard coded
relation.keyFrom
definitions with
var lookupKey = (relation.type === 'belongsTo') ? relation.keyFrom : relation.keyTo;
cheers
@BoLaMN Thanks for providing details on how you patched this. I found an issue with your patch though.
You changed the object being used to pull the targetId in the linkOneToMany function. And that does not work correctly when the subquery pulls in more than one result.
The obj should be target.
function linkOneToMany(target, next) {
var targetId = obj[lookupKey];
var objList = objTargetIdMap[targetId.toString()];
async.each(objList, function(obj, next) {
if (!obj) return next();
obj.__cachedRelations[relationName] = target;
processTargetObj(obj, next);
}, next);
}
Should be:
function linkOneToMany(target, next) {
var targetId = target[lookupKey];
var objList = objTargetIdMap[targetId.toString()];
async.each(objList, function(obj, next) {
if (!obj) return next();
obj.__cachedRelations[relationName] = target;
processTargetObj(obj, next);
}, next);
}
Hey @humblepie
You are correct, there was an issue with my fix i forgot to update the details here to include it, i found a few other places which needed to be patched aswell
i ripped out the required changes into a diff patch for you.
https://gist.github.com/BoLaMN/e2fb1473cae8081ac255fdd0cbe927ba
includes a issue with including embeds to do a sub include on embedded models too
Cheers
found one more in relation-definition.js too for queries with the 'related' function.
eg
inst = new User()
inst.profile(function(err, profile) {
console.log(err, profile);
});
have added the diff patch too https://gist.github.com/BoLaMN/e2fb1473cae8081ac255fdd0cbe927ba
Cheers
In the common model defining a foreignKey property in the relation resolves the issue of a localInstance using the wrong key when trying to query for data. (As per @ritch's comment)
// mat.json
...
"relations": {
"origin": {
"type": "hasOne",
"model": "Origin",
"foreignKey": "originId"
}
},
...
I also looked into implementing a code fix such as the one suggested in the patch but swapping the pk and fk in the relation definition is a breaking change and would require a major release.
An alternate solution I considered was to introduce a flag in the relation definition such as generateIdFromParent which if set would generate the id based on Parent Model name for extended models in the absence of a foreign key. Since there is a documented workaround already this seems unnecessary.
As a result of the above investigation I am closing this issue. If there are concerns still regarding this please feel free to comment / open another issue and mention me directly.
Most helpful comment
Any news on this one ? I think I have the same problem...
I have 2 models with a hasone relation :
In appointment.json :
When I try GET /Appointments/{id}/CustomFields here's the response :
I didn't understand how to "set the foreign key in your model-config.json." Tried it but didn't make any difference. Could you please help I've hit a wall there...
Thanks in advance.