Connections Inside an Interface

Hi,

Is it possible to define connections within an interface in GQL for example:

interface Person{
   children: [Person!]
}

Thanks

sure it is.

Well, somehow it doesn’t work.
I used this schema:

interface Person {
    id: ID!
    name: String!
    childrens: [Person]
}

type Parent implements Person {
    is_good: Boolean
}

and the result is in the attached images.

the schema that was generated is in the attached scheme file.
g01.schema (244 Bytes)

Ah, the confusion begins… Learning how interface schema in GQL coordinates to schema in DQL.

The important thing to remember that not everything in the GQL schema gets translated into the DQL schema. Sometimes it is just used to generate the graphql layer and not the schema itself per se.

Having this said, interfaces in GQL are tricky to handle in DQL. Why? Because DQL schema does not have interfaces, lol. So it makes an interface into a type and then all of the other magic is done in the graphql layer. (I say layer, but it is in a single codebase, so more functions than layers)

To use the above GQL schema in DQL you would need to know what fields came from an interface and what interface they came from.

Here would be a DQL query based on the above schema:

{
  node(func: type(Parent)) {
    uid
    Person.name # note that this is using the dotted notation of Interface.predicate
    Parent.is_good # note that this is using the dotted notation of Type.predicate
    Person.childrens { # note edge is using the dotted notation of Interface.edge
      uid
      Person.name
    }
  }
}

Note: I have never built a schema in DQL and have not even referenced the DQL schema after my first week and learning how DQL differed from GQL.

I am newer into interfaces and see more value with them when unions are available to use, but they do have their uses now too. I have created a Tag interface and then use it for all of my different tag types (TaskTags, EventTags, ContactTags, etc.) This allows me to give tag options of what only is for that Type, but reduces me making mostly the same Type over and over again.

2 Likes

Hi, thanks for your response,

Amm the problem is that for some reason when I put a connection inside an interface it is deleted from the schema and not added to the types that implement the interface.
You can see this behavior in the pictures and in the scheme exported from Dgraph.

There might be a bug here or something that I don’t completely understand

@core-devs can you have a look at that please?

@spinelsun

This confusion is arising because you are trying to run DQL queries on a GraphQL schema. For you to do this correctly, you need to understand the mapping from GraphQL to DQL. I would recommend you to use the GraphQL API with a GraphQL compatible editor and run your queries and mutations there. If those don’t work as expected, please letus know.

Now to answer your question, when a type implements an interface, the connections are stored corresponding to the interface and just referenced from the type. So the connections would be referenced by Person.name, Person.childrens and so on but they can still be queries from a Parent. They are not stored as connections for the implementing type. The correct DQL query would be the one pointed out above.

I think we should discourage our GraphQL users to use Ratel becaue its causing unneccessary confusion.

I understand, still, it is very confusing that Ratel shows Person.name and not Person.children predicate
I tried to use GQL to insert data of a parent with one child but it says:

so I inserted a parent without a child and when I try to filter this parent:

What am I doing wrong in each stage and what is the right way to do that?

@pawan your help will be greeted

thanks

So, here are the rules:

  1. You can’t add interfaces, only concrete types can be added.
  2. To use something inside a filter, it must be searchable.

And, here is the explanation for each stage:

  1. You have defined childrens to be a list of Person, which is an interface. There is no way that you can create an interface. You can only refer to an already existing node of an interface using the ID of the node. What you are trying to do there is, you are trying to create a Person named Justin as a child of a Parent named Julia. Violates rule 1, not possible. Instead you can create a Parent named Justin in a separate mutation, and then use the ID of that parent to link to childrens while creating Parent Julia.
  2. In your schema name doesn’t have a @search directive. For a field to be searchable and thus appear in the Filter, it must be either ID, @id or @search. So, just adding the @search directive on name will help you get the capability to filter by name. Like this:
    interface Person {
        id: ID!
        name: String! @search
        childrens: [Person]
    }
    
1 Like

got it thanks