Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Make one of two fields required in GraphQL schema?

Im using Graphcool but this may be a general GraphQL question. Is there a way to make one of two fields required?

For instance say I have a Post type. Posts must be attached to either a Group or to an Event. Can this be specified in the schema?

type Post {
  body: String!
  author: User!
  event: Event // This or group is required
  group: Group // This or event is required
}

My actual requirements are a bit more complicated. Posts can either be attached to an event, or must be attached to a group and a location.

type Post {
  body: String!
  author: User!
  event: Event // Either this is required, 
  group: Group // Or both Group AND Location are required 
  location: Location 
}

So this is valid:

mutation {
  createPost(
   body: "Here is a comment",
   authorId: "<UserID>",
   eventId: "<EventID>"
  ){
    id
  }
}

As is this:

mutation {
  createPost(
   body: "Here is a comment",
   authorId: "<UserID>",
   groupID: "<GroupID>",
   locationID: "<LocationID>"
  ){
    id
  }
}

But this is not:

As is this:

mutation {
  createPost(
   body: "Here is a comment",
   authorId: "<UserID>",
   groupID: "<GroupID>",
  ){
    id
  }
}
like image 351
Evanss Avatar asked Jan 27 '18 13:01

Evanss


People also ask

What 2 pieces make up a GraphQL schema?

The GraphQLSchema object is the core of a GraphQL server When using any of these libraries, your development process is centered around a GraphQLSchema object, consisting of two major components: the schema definition. the actual implementation in the form of resolver functions.

What is __ Typename in GraphQL?

The __typename field returns the object type's name as a String (e.g., Book or Author ). GraphQL clients use an object's __typename for many purposes, such as to determine which type was returned by a field that can return multiple types (i.e., a union or interface).

Can GraphQL have multiple schemas?

It's possible to run multiple PostGraphile schemas in a single Node. js server, either mounting them at different endpoints or on the same URI and use a simple middleware to switch between them.


2 Answers

One way to represent this in the schema is to use unions , in your case it could be something like this:

type LocatedGroup {
  group: Group!
  location: Location!
}

union Attachable = Event | LocatedGroup

type Post {
  body: String!
  author: User!
  attachable: Attachable!
}
like image 114
bigsolom Avatar answered Sep 17 '22 10:09

bigsolom


There's no way you can define your schema to define groups of inputs as required -- each input is individually either nullable (optional) or non-null (required).

The only way to handle this type of scenario is within the resolver for that specific query or mutation. For example:

(obj, {eventId, groupID, locationID}) => {
  if (
    (eventID && !groupID && !locationID) ||
    (groupID && locationID && !eventID)
  ) {
    // resolve normally
  }
  throw new Error('Invalid inputs')
}

It looks like in order to do that with Graphcool, you would have to utilize a custom resolver. See the documentation for more details.

like image 28
Daniel Rearden Avatar answered Sep 18 '22 10:09

Daniel Rearden