Experience Report for Feature Request
What you wanted to do
Map a reverse edge to a GraphQL field instead of using a balanced @hasInverse
field.
type User {
username: String! @id
posts: [Post] @dgraph(pred: "~Post.author")
}
type Post {
id: ID!
content: String
author: User!
}
Why do I need to do this, because I iterated upon my schema and added an inverse edge that I did not have before, see real life use case:
What you actually did
Use a script like Fixing Inverse Relationships to fix my missing inverse edges, since there is no other way in GraphQL schema mapping.
Why that wasn’t great, with examples
Because I had to write this script, install a node environment to run the script, open up a DQL connection, which if I was not familiar with DQL would be an even bigger burden.
Any external references to support your case
Umm, idk, ne04j supports defining relationships with either IN
or OUT
but it is nice in Dgraph not having to define a relationship directive for a simple outbound relationship in GraphQL. Pros/Cons of both.
https://neo4j.com/docs/graphql-manual/current/type-definitions/relationships/
But this IN
and OUT
syntax is supported because neo4j supports bidirectional edges better described at:
TigerGraph’s GraphQL implementation (still in infancy Query only) has a weird handling of reverse edges using what I would term linking types in GraphQL:
All Dgraph would need to do is allow some kind of mapping directive which not only uses the ~
reverse syntax of DQL, but also then for mutations knows to write the predicates in reverse. So instead when you run the mutation:
// GraphQL Schema
type User {
username: String! @id
posts: [Post] @reverse(edge:"author")
}
type Post {
id: ID!
content: String
author: User!
}
mutation AddPostToUser {
updateUser(input: {
filter: { username: { eq: "foo" } }
set: {
posts: [
{
content: "New Post"
}
]
}
}) {
numUIds
}
}
Would equate to the upsert:
upsert {
query {
var_1 as var(func: eq(User.username,"foo")) @type(User)
}
set {
_:new_1 <Dgraph.type> "Post" .
_:new_1 <Post.content> "New Post" .
_:new_1 <Post.author> uid(var_1) .
}
}
And queries:
query {
queryUser {
username
posts {
id
content
}
}
queryPost {
id
content
author {
username
}
}
}
would equate to DQL:
{
queryUser(func: type(User)) {
username: User.username
posts: ~Post.author {
id: uid
content: Post.content
}
}
queryPost(func: type(Post)) {
id: uid
content: Post.content
author: Post.author {
username: User.username
}
}
}
This might become a little challenging when looking at aggregate functions, but I think it would be simple enough possibly?