GraphQL aliases not possible due to dgraph internal graphql+-

I have a simple use case but it seems currently impossible to handle in a fancy way using dgraph:

Lets say I have a schema where texts are inserted along with the localization because as we know there are many languages around the world

type Text implements{
  text: String! @search(by: [trigram, term, fulltext])
  localization: [Localization!]!
}

type Localization implements Metadata {
  """
  en-US, ja-JP, it-IT,...
  """
  tag: String! @search(by: [hash]) 
}

type Film
   id: String @id
   name: Text 
}

lets assume the film “Avengers Endgame” and assume that the japanese name is “Avengers Endugamu”. So we have a film which has 2 different names

{
   id: avengersendgame
   name: //link to the 2 names
}
{
   tag: en-US
}
{
    text: "Avengers Endgame"
    localization: //id of localization en-US
}
{
   tag: ja-JP
}
{
    text: "Avengers Endugamu"
    localization: //id of localization ja-JP
}

what I would like to do is to filter the name and get only the name associated to the localization I need.
In a perfect world the query I would write

queryFilm(filter: {id: {eq: "avengersendgame"}}) {
   name(filter: {localization.tag: {eq: "en-US"}}) {
       text
   }
}

Unfortunately, it seems that filtering on nested property is not something I should think about, so I thought about

queryFilm(filter: {id: {eq: "avengersendgame"}}) {
   name @cascade {
       text
       localization(filter: {tag: {eq: "en-US"}}) {
          tag
       }
   }
}

Now, besides the fact that I’m asking and getting useless information (the localization tag for instance), it starts to become even worse when I try to use aliases to get the name in 2 different localization (for some context, I always need the Japanese name and the name in the language of the client)

queryFilm(filter: {id: {eq: "avengersendgame"}}) {
   user_lang_name: name @cascade {
       text
       localization(filter: {tag: {eq: "en-US"}}) {
          tag
       }
   }
  japanese_name: name @cascade {
       text
       localization(filter: {tag: {eq: "ja-JP"}}) {
          tag
       }
   }
}

returns

{
  "errors": [
    {
      "message": "Dgraph query failed because Dgraph execution failed because : while converting to subgraph: names not allowed multiple times in same sub-query."
    }
  ],
  "data": {
    "queryFilm": []
  }
}

How should I manage this problem? Is the schema wrong? should I wait for some further development of the GraphQL APIs?

Also, the @cascade solution seems to fall off when used in combination with the first filtering both in GraphQL and GraphQL± (the first directive is applied before the cascade, so if the first element fetched do not satisfy the cascade, the query returns an empty result)

Also, the @cascade solution seems to fall off when used in combination with the first filtering both in GraphQL and GraphQL± (the first directive is applied before the cascade, so if the first element fetched do not satisfy the cascade, the query returns an empty result)

You can get the first n element after cascade using the query variables. You first store the UIDs of nodes which are not filtered out by the cascade directive and then select first n from them. Here is an example of GraphQL± query doing it.

{
  u as var(func:has(name)) @cascade
  {
      name
      friend @filter(eq(name, "ashish") {
         name
         age
      }
  }
  
  another(func: uid(u), first:10)
  {
      name
  }
}

you can refer to first-n-returns-not-all-the-items

but I have to fallback to GraphQL±, which is not what my use case requires (i’m trying to serve a graphQL schema without https calls to external resolvers)

Hey @Luscha,

You can define two type of nodes. One of the type can be the master node that contain the id of movie and the other type can store the name of the movie in specific language. Also the second node will be connected to the first node with a localization edge.

Is it possible to create a “localization edge” in graphql? I think I have to use facets to create the concept of localization edge, right?
Furthermore, I use the “Localiation” concept also to localize other resources like “Where a particular distribution has been carried on” EG:

type Distribution implements Metadata {
  """
  Episode, Anime, Manga, Volume, Chapter, ...
  """
  content: Distributable! @hasInverse(field: distributions)
  """
  Organization
  """
  distributor: Organization @hasInverse(field: distributions)
  """
  Stream, Broadcast, Publish, Air, ...
  """
  type: DistributionType! @search(by: [hash])
  from: Date 
  to: Date 
  """
  it_IT -> in italy in italian
  en_US -> in america in english
  ....
  """
  localization: Localization 
}

So I’ll face the problem of filtering by a nested property anyway

Would something like this work for you?

  • Schema
type Text {
  text: String! @search(by: [trigram, term, fulltext])
  lang: String! @search(by: [hash])
}

type Film {
  id: String! @id
  name: [Text!]
}
  • mutation
mutation {
  addFilm(input: [{id: "avengersendgame", name: [{
    text: "Avengers Endgame",
    lang: "en-US",
  },{
    text: "Avengers Endugamu",
    lang: "ja-JP",
  }]}]) {
    film {
      id
      name {
        text 
        lang
      }
    }
  }
}
  • Query for the movie in en-US
query {
  queryFilm(filter: {id: {eq: "avengersendgame"}}) {
    name(filter: {lang: {eq: "en-US"}}) {
      text
      lang
    }
  }
}
  • Query for the movie in en-US or ja-JP
query {
  queryFilm(filter: {id: {eq: "avengersendgame"}}) {
    name(filter: {lang: {eq: "en-US"}, or: {lang: {eq: "ja-JP"}}}) {
      text
      lang
    }
  }
}

We also have support for lang tags in GraphQL±, support for that hasn’t been added to GraphQL yet. If we had that, then there might be better ways of doing this for you.

Dgraph query failed because Dgraph execution failed because : while converting to subgraph: names not allowed multiple times in same sub-query.

This looks like a bug and we are going to work on fixing it. You should be able to query the same field by using different aliases. GraphQL± allows that and so should GraphQL.

I’ve designed the schema in such a way to exploit the relation to traverse almost every kind of enttity:

type Text implements Metadata {
  text: String! @search(by: [trigram, term, fulltext])
  localization: [Localization!]!
}

type Country implements Metadata {
  ISO_3166_1_ALPHA_2: String! @search(by: [term])
  ISO_3166_1_ALPHA_3: String! @search(by: [term])
}

type Language implements Metadata {
  ISO_639_1: String! @search(by: [hash])
  ISO_639_3: String! @search(by: [hash])
}

type Localization implements Metadata {
  """
  en-US, ...
  """
  tag: String! @search(by: [hash])
  country: Country!
  language: Language!
}

type Address implements Metadata {
  formattedAddress: String! @search(by: [hash])
  addressLine1: String! @search(by: [hash])
  addressLine2: String! @search(by: [hash])
  administrativeAreaLevel1: String! @search(by: [hash])
  administrativeAreaLevel2: String! @search(by: [hash])
  country: Country!
  locality: String! @search(by: [hash])
  postalCode: String! @search(by: [hash])
  route: String! @search(by: [hash])
  streetNumber: String! @search(by: [hash])
  lat: Float! @search
  lng: Float! @search
  googleMapsPlaceId: String! @search
}

Those are some examples of the “core” entities od my schema.
I’ll not post the entire schema because it is 700 lines long, but long short from what I could understand dgraph performs the best when the data is inserted in a node-driven way instead of attribute-driven.
Having the localization as a node instead of a facet or an attribute, for example, allows to traverse the graph (using graphql±) in order to answer query like:

Given a person (which has an addresscountry), give me all films (which has a namelocalized) which do not have the name translated in the language spoken in the the person’s address country AND which has not yet distributed (distribution node → has localization link) in such country

The question seems artificial, but I’m building an open data enciclopedia which should allow the user to bend the data as he pleases.

I know the thread is going off topic, and I wouldn’t mind open another. but since dgraph works better with nodes rather than attributes, I need to find a clean way to filter node based on nested node’s attributes.

Alternatively, if the core team, or whoever knows better than me how dgraph should be used, could give a “best practice guideline” about how to design a schema which is both suitable for graphql but do not lose query answering power I would be more than happy to confront with it