hasInverse and how its different from using @reverse on predicates

Users of GraphQL± would know that we have @reverse index that allows you to automatically create reverse edges.

In GraphQL, we have @hasInverse.

type Author {
    ...
    posts: [Post] @hasInverse(field: author)
}
type Post {
    ...
    author: Author
}

So adding a post for an author also adds the author for the post and vice versa.

Under the hood, this is not implemented using @reverse index. There are two separate predicates created here, i.e.

  • Author.posts: [uid]
  • Post.author: uid.

This is because if we were using @reverse instead of creating two different predicates:

  • There is no way to mutate along the reverse edge direction in GraphQL±. So in the example above, you can add both a post for an author and the author for a post. In GraphQL±, you could only do one of those operations.
  • The reverse edge in GraphQL± has to always be of type [uid] which is again limiting. We don’t have that restriction in GraphQL.

Like for @reverse while using @hasInverse we do the deletion in the inverse direction when a deletion in the forward direction happens to make sure there are no dangling edges. So when you delete a post for an author, we also delete the author from the post.

References

3 Likes

Does this mean that when using @hasinverse, I need to import double relation data when using bulk to import data?

1 Like

I hit the same challenge here: Reverse Edges when using both DQL and GraphQL . For my application I had to stop using reverse edges, and instead managed the inverse predicates myself. This works fine in both GraphQL and DQL, but has some code overhead, and has some side effects (e.g. I also now need to duplicate all the facets, reverse edges store facets once for both directions). I’d therefore love for this to be “unified” in Dgraph across both schema types.

I think it could be acheived by allowing reverse edges in DQL to have a defined alias? I.e. instead of owns and ~owns, we alias ~owns to ownedBy? Then we could do @hasInverse(field: ownedBy) in the GraphQL schema. Behind the scenes ownedBy could still operate as a reverse edge, i.e. be auto generated and shares facets with owns.

1 Like

My fault is that it has been supported in v20.07.0.
For me, I just need to change the schema from

type person {
    id: String! @id @search(by: [hash])
    primary_name: String @search(by: [term,fulltext])
    portray: [character] @dgraph(pred: "~character.performance")
}
type character {
    primary_name: String! @search(by: [term])
    performance: person @hasInverse(field: portray)
}

to

type person {
    id: String! @id @search(by: [hash])
    primary_name: String @search(by: [term,fulltext])
    portray: [character] @dgraph(pred: "~character.performance")
}
type character {
    primary_name: String! @search(by: [term])
    performance: person @dgraph(pred: "character.performance")
}
1 Like