{"action":"opened","issue":{"url":"https://api.github.com/repos/js-data/js-data/issues/116","labels_url":"https://api.github.com/repos/js-data/js-data/issues/116/labels{/name}","comments_url":"https://api.github.com/repos/js-data/js-data/issues/116/comments","events_url":"https://api.github.com/repos/js-data/js-data/issues/116/events","html_url":"https://github.com/js-data/js-data/issues/116","id":67693933,"number":116,"title":"Allow compound keys","user":{"login":"WillsB3","id":868834,"avatar_url":"https://avatars.githubusercontent.com/u/868834?v=3","gravatar_id":"","url":"https://api.github.com/users/WillsB3","html_url":"https://github.com/WillsB3","followers_url":"https://api.github.com/users/WillsB3/followers","following_url":"https://api.github.com/users/WillsB3/following{/other_user}","gists_url":"https://api.github.com/users/WillsB3/gists{/gist_id}","starred_url":"https://api.github.com/users/WillsB3/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/WillsB3/subscriptions","organizations_url":"https://api.github.com/users/WillsB3/orgs","repos_url":"https://api.github.com/users/WillsB3/repos","events_url":"https://api.github.com/users/WillsB3/events{/privacy}","received_events_url":"https://api.github.com/users/WillsB3/received_events","type":"User","site_admin":false},"labels":[],"state":"open","locked":false,"assignee":null,"milestone":null,"comments":0,"created_at":"2015-04-10T22:12:37Z","updated_at":"2015-04-10T22:12:37Z","closed_at":null,"body":"**Apologies in advance for the length of this issue…**\r\n\r\nWe’re trying to get an implementation working where one of our resources uses a compound primary key.\r\n\r\nWe have a parent model (lets call it `Collection`) which has a relation to a child model (lets call it `Document`). Documents represent resources that come from an external site. We use the Document ID from the external site in our URLs so users can correlate the resource on our site with the resource on the external site.\r\n\r\nWhen viewing one of the child models in our system in the context of one of these “collections” the user facing URL looks like this: `/collection/:collection_id/document/:document_id`.\r\n\r\nWe can’t use only the document_id as the primary key for Documents because a single document may exit in multiple “collections”, so to uniquely identify a “document” instance from within our system you need to know both `collection_id` and `document_id`. Thus the API endpoint to fetch details for a specific Document instance is `/api/collection/:collection_id/document/:document_id`. \r\n\r\nIt sounds strange but there are reasons why documents exist in the context of collections. For example users can override certain data on a specific Document, but this edited data is only relevant for the Document instance within the users Collection, so users which have another copy of the same original Document (remember, Documents originate from an external site) in another collection don’t see this overridden/edited data.\r\n\r\nIf it helps I can try and set up a Plunkr with this scenario (of collections and documents) to show the resource definitions we have, but essentially we have a `belongsTo` relation in our `Document` resource definition that looks like this:\r\n\r\n```js\r\nDS.defineResource({\r\n\tname: 'document',\r\n\r\n\trelations: {\r\n\t\tbelongsTo: {\r\n\t\t\tcollection: {\r\n\t\t\t\tparent: true,\r\n\t\t\t\tlocalField: 'collection',\r\n\t\t\t\tlocalKey: 'collection_id'\r\n\t\t\t}\r\n\t\t}\r\n\t}\t\r\n});\r\n```\r\n\r\nWe currently have nothing special (in fact very little at all) in our `Collection` resource definition:\r\n\r\n```js\r\nDS.defineResource({\r\n\tname: 'collection'\r\n});\r\n```\r\n\r\n(We haven’t added the reverse hasMany relation here yet as we may not need it).\r\n\r\nOur difficulty comes in trying to fetch a `Document` from the server using `.find()`. We don’t have a single field on the `Document` model that can be used to uniquely identify a given instance of Document within a collection. However given that the document view exists within a Collection (user facing URL `/collection/:collection_id/document/:document_id`) we know both the collection_id and document_id, so to fetch the Document instance we need to perform a `GET` to `/api/collection/:collection_id/document/:document_id/`. This is the key part of the issue. \r\n\r\nAs far as I can tell, there is no way to inform js-data that the only way to be able to fetch a Document is by combining the `document_id` with the `collection_id`. js-data is obviously aware of the relation between Document and Collection, and if document_id itself were unique js-data would be able to handle the call to `/api/collection/:collection_id/document/:document_id/` because of the `parent: true` declaration in the resource config, but currently js-data doesn’t know that both the collection_id and document_id comprise the compound primary key.\r\n\r\nIs there some way that js-data could be configured so that it can understand this sort of compound key? Perhaps something like this would be possible:\r\n\r\n```js\r\nDS.defineResource({\r\n\tname: 'document',\r\n\tcompoundKey: {\r\n\t\tparts: {\r\n\t\t\tcollection: 'id',\r\n\t\t\tself: 'id'\r\n\t\t}\r\n\t}\r\n\r\n\trelations: {\r\n\t\tbelongsTo: {\r\n\t\t\tcollection: {\r\n\t\t\t\tparent: true,\r\n\t\t\t\tlocalField: 'collection',\r\n\t\t\t\tlocalKey: 'collection_id'\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n});\r\n```\r\n\r\nIn this example the `parts` object lists the relations and the field on the relation that is used as part of the compound key. `self` is a special case key which refers to the current resource type (it could just as easily be `document: 'id'`)\r\n\r\nMaybe something even simpler is possible:\r\n\r\n```js\r\nDS.defineResource({\r\n\tname: 'document',\r\n\trelations: {\r\n\t\tbelongsTo: {\r\n\t\t\tcollection: {\r\n\t\t\t\tparent: true,\r\n\t\t\t\tcompoundKey: true,\r\n\t\t\t\tlocalField: 'collection',\r\n\t\t\t\tlocalKey: 'collection_id'\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n});\r\n```\r\n\r\nIn this case perhaps the compoundKey setting could be checked if `parent: true` is set. If both `parent: true` and `compoundKey: true` are set, then js-data would know that in order to work with Document resources it needs to use both the Document id and id of the relation that has the parent: true setting.\r\n\r\nBoth of these are just quick suggestions, no doubt they’d need more thought/refinement.\r\n\r\nWe had tried setting the id attribute of our Document model to a computed property which used the collection_id and document_id combined with a separator, something like this:\r\n\r\n```js\r\nDS.defineResource({\r\n\tname: 'document',\r\n\r\n\trelations: {\r\n\t\tbelongsTo: {\r\n\t\t\tcollection: {\r\n\t\t\t\tparent: true,\r\n\t\t\t\tlocalField: 'collection',\r\n\t\t\t\tlocalKey: 'collection_id'\r\n\t\t\t}\r\n\t\t}\r\n\t},\r\n\t\r\n\tcomputed: {\r\n\t\tc_id: ['collection_id', 'document_id', function (collectionId, documentId) {\r\n\t\t\t\t\treturn collectionId + ':' + documentId;\r\n\t\t\t\t}]\r\n\t}\r\n\r\n});\r\n```\r\n\r\nBut of course when trying to fetch or save a `Document` resource the requests look something like this for a document with id A12345 in a Collection with id 12: `/api/collection/12/document/12:A12345` which is obviously incorrect.\r\n\r\nWhat do you think? Do you think it will be possible for js-data to be able to handle this kind of relationship?"}}