One Way vs. Two Way @hasInverse

Can someone explain if there is any difference in making a one way @hasInverse vs. making a two way @hasInverse?

Type Person {
  id: ID!
  friends: [Person] @hasInverse(field: friends)
  hasPosts: [Post] @hasInverse(field: author)
  aboutMe: [Post]
}
Type Post {
  id: ID!
  author: Person! @hasInverse(field: hasPosts)
  about: Person @hasInverse(field: aboutMe)
}

In this example:

  • Person.friends is a two way relation
  • Person.hasPosts <-> Post.author is a two way relation
  • Post.about -> Person.aboutMe is a one way relation

Is this a valid schema?
Would there be any reason to do this?
Does this automatically convert it to a 2 way relationship?

Also is it possible to somehow do a 3+ way relation?

User {
  username: String! @id
  editablePosts: [Post]
  myPosts: [Post]
}
Post {
  id: ID!
  author: User! @hasInverse(field: editablePost, field: myPosts)
  editors: [User] @hasInverse(field: editablePost)
  content: String
}

I think the above would be invalid format. Basically the goal in mind would to auto link two properties to a single property in another field. This goes in line with the original question if this is what 1 way relationships actually do.

1 Like

Hi,
Your first schema is valid. You can have all type of relationships. By having Person.hasPosts <-> Post.author , we can have posts which refer to author and author which refer to post. It gives you way to add links by both directions, there may be some use case of it though there is no harm if you use only one way @hasinverse.
I am not sure what you will get from

friends: [Person] @hasInverse(field: friends)
Because , i guess functionality will be same if we only have `friends: [Person] , i need to check though.

For the second schema author and editor can’t have @hasInverse(editablePost) at the same time.
But you can have author: User! @hasInverse(field: editablePost, field: myPosts) .

The reason for this is that in first case if we enter any value in editpost then it should be reflected in both author and editor, they will have some duplicate values for all authors/editors which link to User.
Also there can be other problems in that case.

If you need this type of relationship share your detailed schema , we will look into it and find a wayout.
And for second case it’s valid because edipost/mypost can refer to author and there is no harm in that.

1 Like

Thanks for the answers. I am still learning the correct relations to build but think more of that will be learn as I go.

I had a graphql schema built backed by RDS (MySQL) and custom wrote recolvers and mutations. I had been working on it for ~6 months full time and then started working on the UI as we finished up the API as needs arose. We came to a point where JOINs where just becoming more problematic and some queries we wanted were more and more impossible or very slow. We decided Friday to switch to graphql and then Saturday settled on dGraph. Monday and Tuesday I went through a tutorial and got a simple API up and running. I am on Windows which led to some differences that didn’t work very well with simple tutorials. Today, Wednesday, I built our pretty complex schema fresh and anew in graphql for dgraph and imported it successfully. Still have to write @auth directives to make it secure but the overall mutations, queries, and filters that get generated based off from the schema alone is massive!

In other words, I did in 3 days, what took 6 months before.

12 Likes

Awesome. Good to hear how dgraph solved your problem so fast.
Let us know if you face any issue setting up your project with graphql and dgraph.

1 Like

Not working in my particular use case :thinking:

type Relation {
  id:ID
  name: String
  from: Field @hasInverse(field:"relation")
  fromRoleName: String
  to: Field @hasInverse(field:"relation")
  toRoleName: String
}

type Field {
  id:ID
  name: String!
  relation: Relation @hasInverse(field:"to", field:"from")
}

Error:

resolving updateGQLSchema failed because input:95: Type Relation; Field from: @hasInverse should be consistant. Relation.from is the inverse of Field.relation, but Field.relation is the inverse of Relation.to.

It ignores the second field

1 Like