{"action":"created","issue":{"url":"https://api.github.com/repos/keystonejs/keystone/issues/932","labels_url":"https://api.github.com/repos/keystonejs/keystone/issues/932/labels{/name}","comments_url":"https://api.github.com/repos/keystonejs/keystone/issues/932/comments","events_url":"https://api.github.com/repos/keystonejs/keystone/issues/932/events","html_url":"https://github.com/keystonejs/keystone/issues/932","id":55035129,"number":932,"title":"Relationship Field throws Error if _id has a Non-ObjectID value","user":{"login":"Johnster03","id":10633096,"avatar_url":"https://avatars.githubusercontent.com/u/10633096?v=3","gravatar_id":"","url":"https://api.github.com/users/Johnster03","html_url":"https://github.com/Johnster03","followers_url":"https://api.github.com/users/Johnster03/followers","following_url":"https://api.github.com/users/Johnster03/following{/other_user}","gists_url":"https://api.github.com/users/Johnster03/gists{/gist_id}","starred_url":"https://api.github.com/users/Johnster03/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/Johnster03/subscriptions","organizations_url":"https://api.github.com/users/Johnster03/orgs","repos_url":"https://api.github.com/users/Johnster03/repos","events_url":"https://api.github.com/users/Johnster03/events{/privacy}","received_events_url":"https://api.github.com/users/Johnster03/received_events","type":"User","site_admin":false},"labels":[],"state":"open","locked":false,"assignee":null,"milestone":null,"comments":1,"created_at":"2015-01-21T15:42:02Z","updated_at":"2015-01-21T17:23:39Z","closed_at":null,"body":"CastError: Cast to ObjectId failed for value \"horror\" at path \"genres\"\r\n  at ObjectId.cast (/home/mine/Projects/yttw/node_modules/keystone/node_modules/mongoose/lib/schema/objectid.js:116:13)\r\n\r\nThe thing that I am trying to do is to add multiple genres to a game. Those are the Genre and Games models:\r\n\r\nGenre.js - Model:\r\n\r\n    var keystone = require('keystone'),\r\n            Types = keystone.Field.Types;\r\n     \r\n    var Genre = new keystone.List('Genre', {\r\n            autokey: { from: 'name', path: '_id', unique: true }\r\n    });\r\n     \r\n    Genre.add({\r\n            name_de: { type: String, required: true, initial: true  },\r\n            name: { type: String, required: true, initial: true  }\r\n    });\r\n     \r\n    Genre.relationship({ ref: 'Game', path: 'genres' });\r\n     \r\n    Genre.defaultColumns = 'name_de, name';\r\n     \r\n    Genre.register();\r\n\r\n\r\n\r\nGame.js - Model\r\n\r\n    var keystone = require('keystone'),\r\n            Types = keystone.Field.Types;\r\n     \r\n    var Game= new keystone.List('Game', {\r\n            autokey: { from: 'name', path: '_id', unique: true }\r\n    });\r\n     \r\n    Game.add({\r\n            name_de: { type: String, required: true, initial: true, unique: true },\r\n            name: { type: String, required: true, initial: true, unique: true  },\r\n            intro_de: { type: String, required: true, initial: true  },\r\n            intro_en: { type: String, required: true, initial: true  },\r\n            thumb_sm: { type: Types.Url },\r\n            thumb_lg: { type: Types.Url },\r\n            banner: { type: Types.Url },\r\n            genres: { type: Types.Relationship, ref: 'Genre', many: true }\r\n    });\r\n     \r\n    Game.defaultColumns = 'name_de, name, genres';\r\n    Game.register();\r\n\r\nThe special thing about those models is that the \"_id\" value is created by using autokey from the name field, which causes the _id field to be a String and not an ObjectId. Inserting documents via the keystone backend works like a charm and it also creates the \"_id\" field as intended:\r\n\r\n>db.genres.find()\r\n{ \"_id\" : \"survival\", \"name\" : \"Survival\", \"name_de\" : \"Survival\", \"__v\" : 0 }\r\n{ \"_id\" : \"horror\", \"name\" : \"Horror\", \"name_de\" : \"Horror\", \"__v\" : 0 }\r\n>db.games.find()\r\n{ \"_id\" : \"the-forest\", \"intro_en\" : \"asdfjd;ksf\", \"intro_de\" : \"asdjaskd\", \"name\" : \"The Forest\", \"name_de\" : \"The Forest\", \"genres\" : [ ], \"__v\" : 0 }\r\n\r\nHowever, once I try to add the genres to the game via the keystone backend, it throws the following error:\r\n\r\nCastError: Cast to ObjectId failed for value \"horror\" at path \"genres\"\r\n  at ObjectId.cast (/home/mine/Projects/yttw/node_modules/keystone/node_modules/mongoose/lib/schema/objectid.js:116:13)\r\n\r\nFull error here: http://pastebin.com/JPsDAc4H\r\n\r\nThe problem seems to be that Keystone/Mongoose expects an ObjectId field and does not accept non-ObjectId values for the Relationship/_id field.\r\n\r\nThe interesting thing is that the autocomplete in the keystone backend for the \"genres\" field in the Games model correctly finds the genres from the Genre collection, however they cannot be added as it results in the error above.\r\n\r\nThe reason why I want to do have strings as _ids is because of the already unique value of the name field. I also want to create in a later step to allow the game model to have multiple children of its own model as documented here:\r\n\r\nhttp://docs.mongodb.org/manual/tutorial/model-tree-structures-with-child-references/"},"comment":{"url":"https://api.github.com/repos/keystonejs/keystone/issues/comments/70880791","html_url":"https://github.com/keystonejs/keystone/issues/932#issuecomment-70880791","issue_url":"https://api.github.com/repos/keystonejs/keystone/issues/932","id":70880791,"user":{"login":"Johnster03","id":10633096,"avatar_url":"https://avatars.githubusercontent.com/u/10633096?v=3","gravatar_id":"","url":"https://api.github.com/users/Johnster03","html_url":"https://github.com/Johnster03","followers_url":"https://api.github.com/users/Johnster03/followers","following_url":"https://api.github.com/users/Johnster03/following{/other_user}","gists_url":"https://api.github.com/users/Johnster03/gists{/gist_id}","starred_url":"https://api.github.com/users/Johnster03/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/Johnster03/subscriptions","organizations_url":"https://api.github.com/users/Johnster03/orgs","repos_url":"https://api.github.com/users/Johnster03/repos","events_url":"https://api.github.com/users/Johnster03/events{/privacy}","received_events_url":"https://api.github.com/users/Johnster03/received_events","type":"User","site_admin":false},"created_at":"2015-01-21T17:23:39Z","updated_at":"2015-01-21T17:23:39Z","body":"I found the cause of the problem.\r\n\r\nIn the /node_modules/keystone/lib/fieldTypes/relationship.js file, the nativeType (schema type) is defined as ObjectId. Here is the function (from line 17 in the file):\r\n\r\n\tfunction relationship(list, path, options) {\r\n\t\r\n\t\tthis.many = (options.many) ? true : false;\r\n\t\tthis.filters = options.filters;\r\n\t\t**this._nativeType = keystone.mongoose.Schema.Types.ObjectId;**\r\n\t\tthis._underscoreMethods = ['format'];\r\n\t\r\n\t\trelationship.super_.call(this, list, path, options);\r\n\t\r\n\t}\r\n\r\nI changed the nativeType to mixed, which solved the CastError problem described earlier as it now allows any _id field be any type and not only ObjectIds. This is the new function with the mixed schema type:\r\n\r\n\tfunction relationship(list, path, options) {\r\n\t\r\n\t\tthis.many = (options.many) ? true : false;\r\n\t\tthis.filters = options.filters;\r\n\t\tthis._nativeType = keystone.mongoose.Schema.Types.Mixed;\r\n\t\tthis._underscoreMethods = ['format'];\r\n\t\r\n\t\trelationship.super_.call(this, list, path, options);\r\n\t\r\n\t}\r\n\r\nI tested CRUD ops and population which all seem to work. However, as the mixed schema type allows basically all kinds of input, this should be further tested whether this is an acceptable solution or whether it may cause any potential issues within keystone or other concerns. \r\n\r\nMaybe a keystone developer can look into this. :)"}}