Hi guys,
I have the following scenario.
I made a GET to the following address: /accounts/{id}/apps/{fk}
With the id and fk
id: 54dc9dec466d681300289184
fk: 550715659866120300128497 (_ObjectId but its also Integer_)
I'm using Mongo and both id and fk were auto generated.
The result from the API:
{
"error": {
"name": "Error",
"status": 404,
"message": "No instance with id 5.507156598661203e+23 found for App",
"statusCode": 404
}
}
My App model:
{
"name": "App",
"plural": "apps",
"base": "PersistedModel",
"idInjection": true,
"properties": {
"name": {
"type": "string",
"required": true
},
"appId": {
"type": "string",
"required": false,
"index": {
"unique": true
}
},
"active": {
"type": "boolean",
"default": true
},
"created": {
"type": "date"
},
"modified": {
"type": "date"
}
},
"validations": [],
"relations": {
"account": {
"type": "belongsTo",
"model": "Account",
"foreignKey": ""
}
},
"acls": [],
"methods": []
}
@ritch strong-remoting is confused by the special MongoDB object id literal (550715659866120300128497) and parses it into a number. Unfortunately, the number loses the precision and it cannot be formatted as hex to test the object id pattern.
Strong-remoting needs to know what type it should use for those arguments. Since it isn't explicit it tries to convert it to an integer (since it looks like one).
You can be explicit about the type by modifying the accepts array for the SharedMethod. You can get the shared method using MyModel.sharedClass.find(). See these links for more:
http://apidocs.strongloop.com/strong-remoting/#sharedmethod
http://apidocs.strongloop.com/strong-remoting/#sharedclass-prototype-find
http://apidocs.strongloop.com/strong-remoting/#sharedclass-prototype-methods
At the moment, the fk argument is typed as any. See https://github.com/strongloop/loopback/blob/master/lib/model.js#L497-L499.
@raymondfeng & @ritch Thanks!
Can I force the type in the .json?
At the moment, the fk argument is typed as any
I wonder if we can set that to string if we know that the dataSource is going to use string-ish IDs.
@ritch @raymondfeng Is there a simpler way to force the fk to string.
Wondering why no one else run into this problem before.
Currently the fix causes problems with auto-generated ids for Mongo -- loopback now tries to force datatype to number if id is not explicitly defined in model definition file, whereas before (current HEAD) it let Mongo to decide what datatype id should be.
So GETting /api/myModel/550be5c213cd775eb14e7edb throws id must be a number.
Could the mongo connector provide a new type? This would be very useful in a lots of situations.
Would be nice to also find a solution fixing id comparison with a param, right now we always need to cast the Id to string.
Pending pull request to fix the problem: #1221
It there a fix now? What is the recommended workaround?
We found this problem in the production system of our application. Some instances cannot be retrieved because the ObjectId values are converted to number.
This bug is really critical to us!
Same as seemike, can we have a feedback please ?
Thanks
We are also facing the same issue on our production environment wherein we are not able to fetch the documents which have auto generated long numeric ids.
loopback version:2.13.0
loopback-connector-mongodb version:1.8.0
Is there a workaround for this issue.
For us the workaroud was to change the ID generation. We now use String uuids for all collections that previously had MongoDB ObjectIds. The uuid String never looks like a number to Loobback, so documents with UUID ids are not affected by the problem.
To do that, we use the module 'node-uuid' and add an beforeSave hook on our models like that:
/**
* generate UUID String id field for model
* @param Model
*/
function generateUUID(Model){
Model.observe('before save', function (ctx, next) {
var isNew = ctx.instance && ctx.isNewInstance;
if (!isNew || ctx.instance.id) {
return next();
}else{
ctx.instance.id = uuid.v4();
return next();
}
});
}
@seemike This will work for new models, but not for existing ones. Is there any workaround for existing models with such ids
The #1870 is related to this or is the same bug?
While we wait, my workaround to have my id's working with long number is this:
In files node_modules/loopback/lib/model.js and persisted-model.js
replace all ocurrences of "arg: 'id', type: 'any'" for "arg: 'id', type: 'string'"
Why couldn't there be an ObjectId type to put into the json that generates the model? Then it is fairly explicit how the key is stored. Maybe that extension is built into the mongo connector.
Just started seeing this yesterday and it is causing us massive issues on live (having to go in and manually alter the data for users). Will have a look at solutions provided but just wanted to add my +1.
Note to whomever is picking this up: Check if this is still an issue in LB 3.x first!
@ritch @raymondfeng @cossou Any suggestions for fixing this in 2.x?
My team and I are fighting this issue in production and it's causing a lot of problems. I'm currently running a fork with hardcoded string id relations. I'm hoping there's a better fix: I would really like to continue using 2.x as we have a large codebase build around it. In the meantime, I suppose I must work towards a 3.0 migration...
This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.
This issue has been closed due to continued inactivity. Thank you for your understanding. If you believe this to be in error, please contact one of the code owners, listed in the CODEOWNERS file at the top-level of this repository.
Most helpful comment
Just started seeing this yesterday and it is causing us massive issues on live (having to go in and manually alter the data for users). Will have a look at solutions provided but just wanted to add my +1.