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.
Updates since original post:
@linkTable was renamed to @relationTableembedded directiveExamples
The type Post is marked as embedded. In the underlying database there will be a document for each Blog and all related Posts will be stored inside it.
type Blog {
id: ID! @id
name: String!
posts: [Post]
}
type Post @embedded {
title: String!
}
The same example as before, but the embedded type Post is referenced by one more type.
type Blog {
id: ID! @id
name: String!
posts: [Post]
}
type BestPostsOfTheYear {
id: ID! @id
year: Int!
posts: [Post]
}
type Post @embedded {
title: String!
}
relation directiveBlogToPost for a relation between Blog and Post. It is required if a custom relation table is specified. The name of relation must match the name of type that specifies the shape of the relation table.SET_NULLSET_NULL, CASCADE, "SET_NULL", "CASCADE"TABLE for many to many relations in SQL. This is not always possible.INLINE: This mode stores the relation links within the current type.TABLE: This mode creates a relation table. This is the default for many-to-many relations in SQL.Examples
Specifying a relation name for an ambiguous relation.
type Blog {
id: ID! @id
posts: [Post] @relation(name: "BlogToPost")
posts2: [Post] @relation(name: "BlogToPost2")
}
type Post {
id: ID! @id
blog: Blog @relation(name: "BlogToPost")
blog2: Blog @relation(name: "BlogToPost2")
}
Specifying a cascade for the type Blog.
type Blog {
id: ID! @id
posts: [Post] @relation(onDelete: CASCADE)
}
type Post {
id: ID! @id
blog: Blog
}
Specifying 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.
type Blog {
id: ID! @id
posts: [Post] @relation(link: INLINE)
}
type Post {
id: ID! @id
title: String!
blog: Blog
}
Forcing the TABLE mode for a one-to-may relation.
type Blog {
id: ID! @id
posts: [Post] @relation(link: TABLE)
tags: [Tag]
}
type Post {
id: ID! @id
title: String!
blog: Blog
}
Forcing the TABLE mode for a one-to-may relation and customising the relation table:
type Blog {
id: ID! @id
posts: [Post] @relation(link: TABLE name: "BlogsToPosts")
tags: [Tag]
}
type Post {
id: ID! @id
title: String!
blog: Blog
}
type BlogsToPosts @relationTable {
blog: Blog!
post: Post!
}
relationTable directive@relationTable type does not need to be specified if the relation table does follow our standard conventions.relationTable must:relation directive's name directiveExamples
An 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.
type Blog {
id: ID! @id
posts: [Post]
}
type Post {
id: ID! @id
blogs: [Blog]
}
An example of a many-to-many relation that does not follow our standard conventions. The name of the relation table and columns are customised.
type Blog {
id: ID! @id
posts: [Post] @relation(name: "BlogsToPosts")
}
type Post {
id: ID! @id
blogs: [Blog]
}
type BlogsToPosts @relationTable {
blog: Blog!
post: Post!
}
The link/INLINE and linkTable solve the problems I ran into. In the meantime, to work around not having them, I might use ID! field types and send multiple queries and join in the app code. So, to easily migrate the data when these features are released it would be good if I could specify the column names. (and it would make migration from other systems easier)
There's a slight misspelling in the relation directive, in the example for "Forcing the TABLE mode for a one-to-may relation."
@relation(mode: TABLE)
Should be
@relation(link: TABLE)
@lfades : Thanks 馃檹 . It's fixed now.
In the last example under the relation directive, shown again below, would the Blog.posts relation directive require a name: "BlogsToPosts" argument?
type Blog {
id: ID! @id
posts: [Post] @relation(link: TABLE)
tags: [Tag]
}
type Post {
id: ID! @id
title: String!
blog: Blog
}
type BlogsToPosts @linkTable {
blog: Blog!
post: Post!
}
@willm78 : This is not decided yet. Making it optional would mean users would have to know our internal defaults. What would you prefer?
@mavilein If you guys can make it look obvious, then that's good, otherwise it's better to be more verbose, probably new users will not see that as "obvious", one good idea there is to always use the name option in examples, but letting know the user that it can be optional, that way new users will not get confused and advanced users can take advantage of it.
@mavilein Personally, I think it's easier to learn new libraries when there's less implicit stuff to trip over. Auto-pluralizing names, for example BlogsToPosts, is a source of frustrating bugs to users who aren't familiar with the defualts. Mongoose is notorious for this https://github.com/Automattic/mongoose/issues/1350 and all of it could have been prevented if the library hadn't tried to be so smart. I prefer predictable any day of the week even if it sometimes might mean a little more boilerplate.
+1 for explicit over implicit.
And if you are going to keep pluralisation, then externalise how you do this.
I had to write some tooling to map between Type Names and pluralized version allType
Then we will require the relation name argument if link: TABLE is used. Thanks for the feedback! I was also leaning to explicitness but did not want to decide on my own :-)
INLINE: This mode stores the relation links within the current type.
The side of this value influences the layout of the database schema.
This is the only mode that is supported by Mongo.
TABLE: This mode creates a relation table. This is the default for many-to-many relations in SQL.
1) Does this mean that mongo connector does not support TABLE link, even for mant-to-many relations?
2) Postgresql connector can also use INLINE link for one-to-one and one-to-many relations (id stored as a foreign key in the table), right?
@beeplin :
@mavilein great!
I know the mongo connector is already available in 1.22, and all datamodel v1.1 issues are labeled as status/next. So will the postgres support for INLINE link be available in 1.23? ;)
@beeplin : No that is too early unfortunately. If things go well it could be available at the end of January.
Cool~ Really appreciate the great works of you guys:)
I'm no professional but I want to say to deal with hierarchical data we could reference the way TypeORM did; in fact, the so called "closure table", is the true adjacency list/relation table in Graph Theory.
The spec doc should be posted to Prisma.io.
I cannot even find these explanations on the office website
Any updates on timing or RPs/branches I can monitor?
Hey! I've found myself on this proposal via the @edge type proposal which was closed and where it was stated that this new proposal would resolve the issue there.
The driving use case for the previous proposal is being able to store data on the relation edges between two nodes. A great example is storing the date an edge/relation was created.
I may be misreading this spec but I'm not sure how it resolves this specific use case. Would you be able to provide some insight here?
To clarify it seemed to be like @linkTable might've resolved this however then I saw that a) table relation link is not compatible with mongo and b) @linkTable must have exactly two fields.
Hey @chrisui, are you referring to something like this? https://github.com/prisma/prisma/issues/4303
In Mongo is it possible to use @embedded and @relation on the same field ? This would work to save a catalog collection embedded and also to have a separate collection to modify/query easily the catalog.
Most helpful comment
Hey! I've found myself on this proposal via the
@edgetype proposal which was closed and where it was stated that this new proposal would resolve the issue there.The driving use case for the previous proposal is being able to store data on the relation edges between two nodes. A great example is storing the date an edge/relation was created.
I may be misreading this spec but I'm not sure how it resolves this specific use case. Would you be able to provide some insight here?
To clarify it seemed to be like
@linkTablemight've resolved this however then I saw that a)tablerelation link is not compatible with mongo and b)@linkTablemust have exactly two fields.