{"action":"created","issue":{"url":"https://api.github.com/repos/prisma/prisma/issues/3406","repository_url":"https://api.github.com/repos/prisma/prisma","labels_url":"https://api.github.com/repos/prisma/prisma/issues/3406/labels{/name}","comments_url":"https://api.github.com/repos/prisma/prisma/issues/3406/comments","events_url":"https://api.github.com/repos/prisma/prisma/issues/3406/events","html_url":"https://github.com/prisma/prisma/issues/3406","id":376378531,"node_id":"MDU6SXNzdWUzNzYzNzg1MzE=","number":3406,"title":"[RFC] Datamodel v2 - Relations","user":{"login":"mavilein","id":2470881,"node_id":"MDQ6VXNlcjI0NzA4ODE=","avatar_url":"https://avatars3.githubusercontent.com/u/2470881?v=4","gravatar_id":"","url":"https://api.github.com/users/mavilein","html_url":"https://github.com/mavilein","followers_url":"https://api.github.com/users/mavilein/followers","following_url":"https://api.github.com/users/mavilein/following{/other_user}","gists_url":"https://api.github.com/users/mavilein/gists{/gist_id}","starred_url":"https://api.github.com/users/mavilein/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/mavilein/subscriptions","organizations_url":"https://api.github.com/users/mavilein/orgs","repos_url":"https://api.github.com/users/mavilein/repos","events_url":"https://api.github.com/users/mavilein/events{/privacy}","received_events_url":"https://api.github.com/users/mavilein/received_events","type":"User","site_admin":false},"labels":[{"id":696956816,"node_id":"MDU6TGFiZWw2OTY5NTY4MTY=","url":"https://api.github.com/repos/prisma/prisma/labels/area/datamodel","name":"area/datamodel","color":"fbca04","default":false},{"id":686893670,"node_id":"MDU6TGFiZWw2ODY4OTM2NzA=","url":"https://api.github.com/repos/prisma/prisma/labels/area/migrations","name":"area/migrations","color":"fbca04","default":false},{"id":707461750,"node_id":"MDU6TGFiZWw3MDc0NjE3NTA=","url":"https://api.github.com/repos/prisma/prisma/labels/proposal/needs-review","name":"proposal/needs-review","color":"b621ff","default":false}],"state":"open","locked":false,"assignee":null,"assignees":[],"milestone":null,"comments":4,"created_at":"2018-11-01T12:48:13Z","updated_at":"2018-12-05T15:48:08Z","closed_at":null,"author_association":"MEMBER","body":"This part of the spec describes the relations used to control relations. See the issue #3408 to learn about the other parts of the spec.\r\n\r\n# The `embedded` directive\r\n\r\n* *valid locations:* type\r\n* *behaviour:* Specifies a type as embedded, which means that the type will be stored along side its parent node. An embedded type has no identity itself. It can only be created or updated through nested mutations.\r\n* *optional:* yes. Defaults to treating a type as not embedded.\r\n* *arguments:* none\r\n* *validation*:\r\n\t* This directive is only allowed if the underlying database supports embedded types. This is the case for Document databases like Mongo.\r\n\r\n*Examples*\r\n\r\nThe type `Post` is marked as embedded. In the underlying database there will be a document for each `Blog` and all related `Post`s will be stored inside it.\r\n\r\n```graphql\r\ntype Blog {\r\n  id: ID! @id\r\n  name: String!\r\n  posts: [Post]\r\n}\r\n\r\ntype Post @embedded {\r\n  title: String!\r\n}\r\n```\r\n\r\nThe same example as before, but the embedded type `Post` is referenced by one more type.\r\n\r\n```graphql\r\ntype Blog {\r\n  id: ID! @id\r\n  name: String!\r\n  posts: [Post]\r\n}\r\n\r\ntype BestPostsOfTheYear {\r\n  id: ID! @id\r\n  year: Int!\r\n  posts: [Post]\r\n}\r\n\r\ntype Post @embedded {\r\n  title: String!\r\n}\r\n```\r\n\r\n# The `relation` directive\r\n\r\n* *valid locations*: on relation fields\r\n* *optional*:\r\n\t* Yes if a relation is not ambiguous.\r\n\t* No if a relation is ambiguous.\r\n\t* A relation between two types is ambiguous if there is more than one relation between those two types.\r\n* *arguments*:\r\n\t* *name: String*\r\n\t\t* The name of the relation.\r\n\t\t* optional: yes. Defaults to an auto generated name, e.g. `BlogToPost` for a relation between `Blog` and `Post`.\r\n\t* *onDelete: Enum | String*\r\n\t\t* Specifies whether this relation is cascading or not. Cascading means that the related nodes get deleted when a node of the current type gets deleted.\r\n\t\t* optional: yes. Defaults to `SET_NULL`\r\n\t\t* valid values: `SET_NULL`, `CASCADE`, `\"SET_NULL\"`, `\"CASCADE\"`\r\n\t* *link: Enum*\r\n\t\t* Specifies the mode that should be used to implement this relation.\r\n\t\t* optional: maybe. Based upon the arity of the relation and the connector a mode is chosen, e.g. `TABLE` for many to many relations in SQL. This is not always possible.\r\n\t\t* valid values:\r\n\t\t\t* `INLINE`: This mode stores the relation links *within the current type*.\r\n\t\t\t\t* The side of this value influences the layout of the database schema.\r\n\t\t\t\t* This is the only mode that is supported by Mongo.\r\n\t\t\t* `TABLE`: This mode creates a relation table. This is the default for many-to-many relations in SQL.\r\n\t\t* validation:\r\n\t\t\t* The mode must be only specified on one side of the relation.\r\n* *validations*:\r\n\t* If a relation is ambiguous and the name needs to be specified the directive needs to be put on both fields belonging to a relation.\r\n        * If a name is provided voluntary it also needs to be on both sides of the relation. \r\n\t* The link argument must not be specified on both sides of a relation.\r\n\t* The link must be specified if it can not be inferred from the data model, e.g. for a 1:1 relation in a SQL database Prisma needs to know on which side the relation link should be stored.\r\n\r\n*Examples*\r\n\r\nSpecifying a relation name for an ambiguous relation.\r\n\r\n```graphql\r\ntype Blog {\r\n  id: ID! @id\r\n  posts: [Post] @relation(name: \"BlogToPost\")\r\n  posts2: [Post] @relation(name: \"BlogToPost2\")\r\n}\r\n\r\ntype Post {\r\n  id: ID! @id\r\n  blog: Blog @relation(name: \"BlogToPost\")\r\n  blog2: Blog @relation(name: \"BlogToPost2\")\r\n}\r\n```\r\n\r\nSpecifying a cascade for the type `Blog`.\r\n\r\n```graphql\r\ntype Blog {\r\n  id: ID! @id\r\n  posts: [Post] @relation(onDelete: CASCADE)\r\n}\r\n\r\ntype Post {\r\n  id: ID! @id\r\n  blog: Blog\r\n}\r\n```\r\n\r\nSpecifying where a relation links gets stored. A document in the `Blog` collection will store an Array of `Post` ids. The directive could be moved to their opposite related field to store the relation links in the `Post` node.\r\n\r\n```graphql\r\ntype Blog {\r\n  id: ID! @id\r\n  posts: [Post] @relation(link: INLINE)\r\n}\r\n\r\ntype Post {\r\n  id: ID! @id\r\n  title: String!\r\n  blog: Blog\r\n}\r\n```\r\n\r\nForcing the `TABLE` mode for a one-to-may relation.\r\n\r\n```graphql\r\ntype Blog {\r\n  id: ID! @id\r\n  posts: [Post] @relation(link: TABLE)\r\n  tags: [Tag]\r\n}\r\n\r\ntype Post {\r\n  id: ID! @id\r\n  title: String!\r\n  blog: Blog\r\n}\r\n```\r\n\r\nForcing the `TABLE` mode for a one-to-may relation and customising the relation table:\r\n\r\n```graphql\r\ntype Blog {\r\n  id: ID! @id\r\n  posts: [Post] @relation(link: TABLE)\r\n  tags: [Tag]\r\n}\r\n\r\ntype Post {\r\n  id: ID! @id\r\n  title: String!\r\n  blog: Blog\r\n}\r\n\r\ntype BlogsToPosts @linkTable {\r\n   blog: Blog!\r\n   post: Post!\r\n}\r\n```\r\n\r\n# The `linkTable` directive\r\n\r\n* *valid locations*: on types\r\n* *behaviour:* This directive marks a type as a relation table. That means it is not a regular type that is included in our API. It simply describes the shape of a relation table.\r\n* *optional*:\r\n\t* The directive itself is not optional if a type represents a relation table.\r\n\t* A `@linkTable` type does not need to be specified if the relation table does follow our standard conventions.\r\n* *arguments:* none\r\n* *validations*:\r\n\t* A type that is marked as `linkTable` must:\r\n\t\t* not be referred in any relation field.\r\n\t\t* contain exactly 2 fields that refer the types that are involved in the relation.\r\n\t\t* must be referenced from a `relation` directive's `name` directive\r\n\t* The directive is only supported by SQL connectors.\r\n\r\n*Examples*\r\n\r\nAn example of a many-to-many relation that follows our standard conventions. Therefore no relation table has to be specified explicitly. The name of the table will be `_BlogToPost` and the columns will be called `A` and `B`.\r\n\r\n```graphql\r\ntype Blog {\r\n  id: ID! @id\r\n  posts: [Post]\r\n}\r\n\r\ntype Post {\r\n  id: ID! @id\r\n  blogs: [Blog]\r\n}\r\n```\r\n\r\nAn example of a many-to-many relation that does not follow our standard conventions. The name of the relation table and columns are customised.\r\n\r\n```graphql\r\ntype Blog {\r\n  id: ID! @id\r\n  posts: [Post] @relation(name: \"BlogsToPosts\")\r\n}\r\n\r\ntype Post {\r\n  id: ID! @id\r\n  blogs: [Blog]\r\n}\r\n\r\ntype BlogsToPosts @linkTable {\r\n   blog: Blog!\r\n   post: Post!\r\n}\r\n```"},"comment":{"url":"https://api.github.com/repos/prisma/prisma/issues/comments/444533245","html_url":"https://github.com/prisma/prisma/issues/3406#issuecomment-444533245","issue_url":"https://api.github.com/repos/prisma/prisma/issues/3406","id":444533245,"node_id":"MDEyOklzc3VlQ29tbWVudDQ0NDUzMzI0NQ==","user":{"login":"mavilein","id":2470881,"node_id":"MDQ6VXNlcjI0NzA4ODE=","avatar_url":"https://avatars3.githubusercontent.com/u/2470881?v=4","gravatar_id":"","url":"https://api.github.com/users/mavilein","html_url":"https://github.com/mavilein","followers_url":"https://api.github.com/users/mavilein/followers","following_url":"https://api.github.com/users/mavilein/following{/other_user}","gists_url":"https://api.github.com/users/mavilein/gists{/gist_id}","starred_url":"https://api.github.com/users/mavilein/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/mavilein/subscriptions","organizations_url":"https://api.github.com/users/mavilein/orgs","repos_url":"https://api.github.com/users/mavilein/repos","events_url":"https://api.github.com/users/mavilein/events{/privacy}","received_events_url":"https://api.github.com/users/mavilein/received_events","type":"User","site_admin":false},"created_at":"2018-12-05T15:48:08Z","updated_at":"2018-12-05T15:48:08Z","author_association":"MEMBER","body":"@willm78 : This is not decided yet. Making it optional would mean users would have to know our internal defaults. What would you prefer?"}}
{"actor":{"display_login":"mavilein"}}