Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What is `... on` doing in this GraphQL?

Tags:

graphql

I am trying to mimic what some GraphQL does, but I do not have access to be able to run the original. It is of the form:

query {
  dataSources(dataType: Ais) {
    ... on AisDataSource {
      messages(filter: {broadcastType: Static}) {
        ... on AisStaticBroadcast {
          field1
          field2

(I have ommitted the closing parentheses).

It is my understanding that ... on is either to include a fragment (none here), or to choose between alternatives (but these are nested). So is this query wrong, or is there more to ... on?

like image 618
schoon Avatar asked Nov 27 '25 21:11

schoon


2 Answers

This

{
  user {
    ... on User {
      id
      username
    }
  }
}

and this

{
  user {
    ...UserFragment
  }
}

fragment UserFragment on User {
  id
  username
}

are equivalent. In both cases, you are using a fragment. In the first example, we simply refer to the fragment as an inline fragment.

When requesting a field that return a composite type (an object, interface or union), you must specify a selection set, or one or more fields for the return type. Since fragments must include a type condition (the on keyword plus the type name), they can be used to specify different selection sets depending on the type that's actually returned at runtime.

{
  user {
    ...RegularUserFragment
    ...AdminFragment
  }
}

fragment RegularUserFragment on RegularUser {
  id
  username
}

fragment AdminFragment on Admin {
  id
  username
  accessLevel
}

All we're saying is "if the type at runtime is this, then return this set of fields". If any of the fields inside the fragment also return a composite type, then those fields also have to specify a selection set for — that means additional fragments can be used inside those selection sets.

like image 120
Daniel Rearden Avatar answered Dec 01 '25 14:12

Daniel Rearden


For those not yet clicked , here's an implementation using appolo graphql

Graphql schema:

  interface Animal {
    name: String
    age: String
    dob: String
    owner: String
    sound: String
  }

  type Dog implements Animal {
    name: String
    age: String
    dob: String
    owner: String
    sound: String
    color: String
  }

  type Cat implements Animal {
    name: String
    age: String
    dob: String
    owner: String
    sound: String
    weight: String
  }


Here Animal is an abstract type and the Dog and Cat has similar properties excpet color and weight which is different.

Resolver:

  Owner: {
    animal: (creator) => {
      return animals.find(anm => creator.name == anm.owner)
    }

  },

  Animal: {
    __resolveType(animal) {
      if (animal.sound == "Bark") {
        return 'Dog'
      } else {
        return 'Cat' 
      }
    }
  },

So a particular owner may have a cat or dog, so we have this scenario where if it's a dog output the color property and if it's a cat output weight. Consider it more like an if else statement.

An example query:

owner(id: $id) {
     animal {
        ... on Cat {
           weight
        }
        ... on Dog {
            color
          }
      }
}

Same query using fragments:

owner(id: $id) {
     animal {
         ...Catto
         ...Doggo
      }
}

fragment Catto on Cat {
  weight
}

fragment Doggo on Dog {
  color
}
like image 34
pv0 Avatar answered Dec 01 '25 13:12

pv0



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!