# Real inverse relation on GraphQL schema

**URL:** <https://discuss.dgraph.io/t/real-inverse-relation-on-graphql-schema/7336>\
**Category:** GraphQL\
**Tags:** graphql\
**Created:** [June 23, 2020, 5:20pm UTC](https://discuss.dgraph.io/t/real-inverse-relation-on-graphql-schema/7336 "2020-06-23T17:20:41Z")\
**Posts on this page:** 13\
**Page:** 1

<div class="post-metadata">

**Author:** ![Luscha](https://yyz1.discourse-cdn.com/flex007/user_avatar/discuss.dgraph.io/luscha/32/3588_2.png) [@Luscha](https://discuss.dgraph.io/u/Luscha)\
**Post date:** [June 23, 2020, 5:20pm UTC](https://discuss.dgraph.io/t/real-inverse-relation-on-graphql-schema/7336/1 "2020-06-23T17:20:41Z")

</div>

I’m currently learning dgraph to implement a quite particular use case.  
long story short I have a system in place which feeds a large quantity of data in dgraph and I’m aiming to serve the data through GraphQL.  
Being GraphQL the only way to query data, I designed the GraphgQL schema first and i built a component that generates the correct RDF to match the GraphQL schema.

Tha major issue I faced using RDF mutation to insert data is the **hasInverse** directive.  
Using this particular directive dgraph generates 2 separate predicate which are kept synced using GraphQL:

```auto
type Text {
	text: String @search(by: [hash])
	is_name: [Person!] @hasInverse(field: name)
}

type Person {
    name: Text!
} 

```

Generates

 ![image](https://canada1.discourse-cdn.com/flex007/uploads/dgraph/original/2X/7/784ed5f2fccea9fc9c7c32469447339a3325a20e.png)  
which is properly handled as long as the data is inserted though GraphQL, for instance, a mutation like

```auto
mutation {
  addPerson(input: [{name: {text: "paolo"}}]) {
    person {
      name {
        text
      }
    }
  }
}

```

creates both the relation Person.name and Text.is\_name

However using RDFs it’s required to build the rdf to manually set both relation in order to keep the schema consistent

```auto
{
 set {
    _:paolo <dgraph.type> "Person" .
    _:name <dgraph.type> "Text" .
    _:name <Text.text> "Paolo" .
    _:paolo <Person.name> _:name .
  	_:name <Text.is_name> _:paolo .
 }
}

```

This becomes quite tricky if the schema grows or if updates / deletions are performed.

Exploiting the **dgraph** directive i figured out how to build a proper inverse relation in order to keep the “link” consistent in GraphQL without the need of update 2 relations:

Having a predicate in dgraph such as  
`Person.name uid` **reverse**  
is possible to insert a GraphQL schema like

```auto
type Text {
	text: String @search(by: [hash])
	is_name: [Person!] @dgraph(pred: "~Person.name")
}

type Person {
    name: Text @dgraph(pred: "Person.name")
} 

```

Updating / inserting / deleting the relation from RDF or GrapQL it stays consistent from the perspective of both dgraph and GraphQL

After 30 lines of context, i would like to ask three things:  
Is this a proper to use dgraph?  
Will the GraphQL implementation change in the near future so that this solution will break?  
Why isn’t this the default behaviour of a GraphQL field with **hasInverse** directive instead of generating 2 different predicates which do not share any information and can lead to predicates pointing to empty / null nodes?

---

<div class="post-metadata">

**Author:** ![vardhanapoorv](https://yyz1.discourse-cdn.com/flex007/user_avatar/discuss.dgraph.io/vardhanapoorv/32/2441_2.png) [@vardhanapoorv](https://discuss.dgraph.io/u/vardhanapoorv)\
**Post date:** [June 24, 2020, 6:55am UTC](https://discuss.dgraph.io/t/real-inverse-relation-on-graphql-schema/7336/2 "2020-06-24T06:55:37Z")

</div>

Hi @Luscha  
The way you suggested if it works for your use case then go ahead, just remember in doing this way you won’t be able to do GraphQL mutation for that edge which has inverse.  
No, it won’t break your current solution.

---

<div class="post-metadata">

**Author:** ![Miaourt](https://yyz1.discourse-cdn.com/flex007/user_avatar/discuss.dgraph.io/miaourt/32/3022_2.png) [@Miaourt](https://discuss.dgraph.io/u/Miaourt)\
**Post date:** [June 24, 2020, 7:34am UTC](https://discuss.dgraph.io/t/real-inverse-relation-on-graphql-schema/7336/3 "2020-06-24T07:34:02Z")

</div>

Hi, I’m happy @Luscha asked this question, it’s quite what was dancing in my head for some time but didn’t took time to phrase it :

Would it be possible, in the future, to have a more “native” reverse field in the graphql schema ? The solution proposed there is quite hacky and needs us to, after loading the schema, ask dgraph to add the “reverse” to Person.name.

Maybe change the default “reverse” to be able to specify a name for it, while still defaulting to “~predicate” ?

---

<div class="post-metadata">

**Author:** ![Luscha](https://yyz1.discourse-cdn.com/flex007/user_avatar/discuss.dgraph.io/luscha/32/3588_2.png) [@Luscha](https://discuss.dgraph.io/u/Luscha)\
**Post date:** [June 24, 2020, 10:29am UTC](https://discuss.dgraph.io/t/real-inverse-relation-on-graphql-schema/7336/4 "2020-06-24T10:29:48Z")

</div>

@vardhanapoorv  
I was expecting some “negative” implications from using this hack. Thank you for your reply.  
I tried the inverse mutation in graphql and as you said it’s no possibile using the reverse edge. I then played around with rdf and i guess i is simply illegal to build an RDF mutation using a reverse edge

```auto
mutation {
  set {
     uid(t1) <~Person.name> uid(p1) .
  }
}

```

Leads to an error, as expected.

I then would like to ask why dgraph has not the capability to perform this kind of mutation.

I actually expected dgraph to be able to mutate an inverse relation, considering the fact that it is able to query it.

---

<div class="post-metadata">

**Author:** ![michaelcompton](https://yyz1.discourse-cdn.com/flex007/user_avatar/discuss.dgraph.io/michaelcompton/32/1774_2.png) [@michaelcompton](https://discuss.dgraph.io/u/michaelcompton)\
**Post date:** [June 24, 2020, 10:46pm UTC](https://discuss.dgraph.io/t/real-inverse-relation-on-graphql-schema/7336/5 "2020-06-24T22:46:35Z")

</div>

Hi, you’re actually bumping into some of the reasons why our GraphQL doesn’t use `@reverse`. Here’s the main reasons:

- `@reverse` doesn’t allow mutations along the reverse edge. That was pretty much a show stopper in itself.
- `@reverse` is always a list in the reverse direction. That creates some modelling issues in GraphQL and when combined with the point above, would restrict how you could model and mutate.
- before we added the `@dgraph` directive, it would have added some complexity to query generation because it’d need a special case to work out that it’s a thing with a reverse and then to add the `~` edge instead of the real one.

I don’t think it’s ‘hacked in’ the way we did it. I actually think (because of the above) the other way of just leaning on reverse would have been the hack because it’d decrease what you can do with the API.  
Where we’ve landed in the end, you get either choice.

I feel like there’s two things for us to do here:

1. Seems like one of the biggest things we are missing is guidance. We don’t really have any good docs atm on how to handle running with GraphQL± and GraphQL at the same time. We also don’t have any docs on bulk loading with GraphQL.

2. The GraphQL schema update has `@dgraph` but it doesn’t preserve some of the Dgraph things like `@count` and `@reverse`, so it wipes some bits of schema, which feels like what @Miaourt is bumping into. I wonder if the solution is to extend `@dgraph` so it can also take other args like `@dgraph(pred: "Person.name", reverse: true)` or `@dgraph(pred: "Person.name", with: [reverse, count])`.

Anything else that could help?

---

<div class="post-metadata">

**Author:** ![Luscha](https://yyz1.discourse-cdn.com/flex007/user_avatar/discuss.dgraph.io/luscha/32/3588_2.png) [@Luscha](https://discuss.dgraph.io/u/Luscha)\
**Post date:** [June 25, 2020, 1:38pm UTC](https://discuss.dgraph.io/t/real-inverse-relation-on-graphql-schema/7336/6 "2020-06-25T13:38:22Z")

</div>

I guess that some guidance to bulk import using graphql would be nice.

Unfortunately today I also discovered that is not possible to use the reverse edge solution combined with interfaces.

```auto
type Object {
   ownedBy: Person @dgraph(pred: "Object.owner")
}

type BusinessMan implements Person {
  companyName: String
}

interface Person {
    name: String
    owns: [Object] @dgraph(pred: "~Object.owner")
} 

```

Leads to an error because when Car is expanded it expect “ownedBy”'s edge to be an edge of type BusinessMan

```auto
couldn't rewrite mutation updateGQLSchema because input:1: Type Object; Field ownedBy: should be of type BusinessMan to be compatible with @dgraph reverse directive but is of type Person.\n

```

Honestly i feel like interfaces present way too much issue when trying to use the full potential of dgraph combining GraphQL+/- and GraphQL

---

<div class="post-metadata">

**Author:** ![michaelcompton](https://yyz1.discourse-cdn.com/flex007/user_avatar/discuss.dgraph.io/michaelcompton/32/1774_2.png) [@michaelcompton](https://discuss.dgraph.io/u/michaelcompton)\
**Post date:** [June 26, 2020, 2:14am UTC](https://discuss.dgraph.io/t/real-inverse-relation-on-graphql-schema/7336/7 "2020-06-26T02:14:42Z")

</div>

Hmmm, I feel like this one should be allowed. There’s some rules that get checked around this one at schema upload time.

I’ll check in with the team to see if there’s any reason why we aren’t letting this case through. I’ll let you know later if it needs to be logged as a bug.

---

<div class="post-metadata">

**Author:** ![Luscha](https://yyz1.discourse-cdn.com/flex007/user_avatar/discuss.dgraph.io/luscha/32/3588_2.png) [@Luscha](https://discuss.dgraph.io/u/Luscha)\
**Post date:** [June 26, 2020, 10:13am UTC](https://discuss.dgraph.io/t/real-inverse-relation-on-graphql-schema/7336/8 "2020-06-26T10:13:45Z")

</div>

Thank you! I’ll wait then

---

<div class="post-metadata">

**Author:** ![pawan](https://yyz1.discourse-cdn.com/flex007/user_avatar/discuss.dgraph.io/pawan/32/1946_2.png) [@pawan](https://discuss.dgraph.io/u/pawan)\
**Post date:** [June 26, 2020, 10:55am UTC](https://discuss.dgraph.io/t/real-inverse-relation-on-graphql-schema/7336/9 "2020-06-26T10:55:22Z")

</div>

I checked this and it looks like a bug to me. Seems like the restriction that we have here is too strict. We wanted to check that in case a type (`BusinessMan`) has a reverse field `owns`, then there should be a field in the reverse type `Object` that is of type BusinessMan but we don’t need that. The type of the field can be BusinessMan or any interface that BusinessMan implements like `Person` here.

Can you please file this as a bug on GitHub so that we can get it fixed?

---

<div class="post-metadata">

**Author:** ![Luscha](https://yyz1.discourse-cdn.com/flex007/user_avatar/discuss.dgraph.io/luscha/32/3588_2.png) [@Luscha](https://discuss.dgraph.io/u/Luscha)\
**Post date:** [June 26, 2020, 1:15pm UTC](https://discuss.dgraph.io/t/real-inverse-relation-on-graphql-schema/7336/10 "2020-06-26T13:15:53Z")

</div>

Sure

---

<div class="post-metadata">

**Author:** ![Luscha](https://yyz1.discourse-cdn.com/flex007/user_avatar/discuss.dgraph.io/luscha/32/3588_2.png) [@Luscha](https://discuss.dgraph.io/u/Luscha)\
**Post date:** [June 26, 2020, 1:26pm UTC](https://discuss.dgraph.io/t/real-inverse-relation-on-graphql-schema/7336/11 "2020-06-26T13:26:03Z")

</div>

Done [Dgraph do not accept valid GraphQL with inverse @dgraph directive · Issue #5744 · dgraph-io/dgraph · GitHub](https://github.com/dgraph-io/dgraph/issues/5744)

---

<div class="post-metadata">

**Author:** ![pawan](https://yyz1.discourse-cdn.com/flex007/user_avatar/discuss.dgraph.io/pawan/32/1946_2.png) [@pawan](https://discuss.dgraph.io/u/pawan)\
**Post date:** [August 7, 2020, 8:31am UTC](https://discuss.dgraph.io/t/real-inverse-relation-on-graphql-schema/7336/12 "2020-08-07T08:31:24Z")

</div>

This was fixed and should be available in the `v20.07.0` release and also master.

---

<div class="post-metadata">

**Author:** ![Luscha](https://yyz1.discourse-cdn.com/flex007/user_avatar/discuss.dgraph.io/luscha/32/3588_2.png) [@Luscha](https://discuss.dgraph.io/u/Luscha)\
**Post date:** [August 9, 2020, 5:05pm UTC](https://discuss.dgraph.io/t/real-inverse-relation-on-graphql-schema/7336/13 "2020-08-09T17:05:16Z")

</div>

It works, thank you
