# I cannot map a reverse edge in GraphQL using @dgraph directive

**URL:** <https://discuss.dgraph.io/t/i-cannot-map-a-reverse-edge-in-graphql-using-dgraph-directive/16367>\
**Category:** GraphQL\
**Tags:** graphql, kind:feature, reverse, hasinverse\
**Created:** [December 19, 2021, 3:58am UTC](https://discuss.dgraph.io/t/i-cannot-map-a-reverse-edge-in-graphql-using-dgraph-directive/16367 "2021-12-19T03:58:55Z")\
**Posts on this page:** 2\
**Page:** 1

<div class="post-metadata">

**Author:** ![amaster507](https://yyz1.discourse-cdn.com/flex007/user_avatar/discuss.dgraph.io/amaster507/32/4123_2.png) [@amaster507](https://discuss.dgraph.io/u/amaster507)\
**Post date:** [December 19, 2021, 3:58am UTC](https://discuss.dgraph.io/t/i-cannot-map-a-reverse-edge-in-graphql-using-dgraph-directive/16367/1 "2021-12-19T03:58:56Z")

</div>

## 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.

```GraphQL
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:

> **[Migrating Data with DQL after changing GraphQL Schema](https://discuss.dgraph.io/t/migrating-data-with-dql-after-changing-graphql-schema/16366)**
>
> Lets say we made these changes to our schema (v21.12+): -type UserEmails { +type UserEmail { + id: ID! email: String @search verified: Boolean @search + owner: User @hasInverse(field: "linkedEmails") } type User { - updatedAt:...

### What you actually did

Use a script like [Fixing Inverse Relationships - Dgraph Cloud / Slash GraphQL - Discuss Dgraph](http://discuss.hypermode.com/t/fixing-inverse-relationships/12888) 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.

> **[Types - Neo4j GraphQL Library](https://neo4j.com/docs/graphql/current/types/)**
>
> This page lists all types available in the Neo4j GraphQL Library.

But this `IN` and `OUT` syntax is supported because neo4j supports bidirectional edges better described at:

> **[Modelling Data in Neo4j: Bidirectional Relationships](https://graphaware.com/blog/neo4j-bidirectional-relationships/)**
>
> Transitioning from the relational world to the beautiful world of graphs requires a shift in thinking about data. Although graphs are often much more

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:

> **[Schema - TigerGraph GraphQL Service](https://docs.tigergraph.com/graphql/3.9/schema)**
>
> The Only Scalable Platform for Analytics and ML on Connected Data

* * *

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:

```auto
// GraphQL Schema
type User {
  username: String! @id
  posts: [Post] @reverse(edge:"author")
}
type Post {
  id: ID!
  content: String
  author: User!
}

```

```auto
mutation AddPostToUser {
  updateUser(input: {
    filter: { username: { eq: "foo" } }
    set: {
      posts: [
        {
          content: "New Post"
        }
      ]
    }
  }) {
    numUIds
  }
}

```

Would equate to the upsert:

```DQL
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:

```GraphQL
query {
  queryUser {
    username
    posts {
      id
      content
    }
  }
  queryPost {
    id
    content
    author {
      username
    }
  }
}

```

would equate to DQL:

```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?

---

<div class="post-metadata">

**Author:** ![amaster507](https://yyz1.discourse-cdn.com/flex007/user_avatar/discuss.dgraph.io/amaster507/32/4123_2.png) [@amaster507](https://discuss.dgraph.io/u/amaster507)\
**Post date:** [December 19, 2021, 4:07am UTC](https://discuss.dgraph.io/t/i-cannot-map-a-reverse-edge-in-graphql-using-dgraph-directive/16367/2 "2021-12-19T04:07:58Z")

</div>

Maybe the [@core-devs](https://discuss.dgraph.io/groups/core-devs) could link to any relative discussions on why the choice was made to use two edges outbound from each type instead of using the inverse edge on one side. I am guessing it was for schema iteration where in case the reverse edge was no longer part of the GraphQL schema the inverse edge would still be an actual edge, but maybe there is more to it? Performance? Ease of Implementation? Lazy Programming (nothing wrong with this for quick iterations)?
