⚠️ This lesson is retired and might contain outdated information.

Write a GraphQL Mutation

Josh Black
InstructorJosh Black
Share this video with your friends

Social Share Links

Send Tweet
Published 7 years ago
Updated 2 years ago

In order to change the data that we can query for in a GraphQL Schema, we have to define what is called a mutation in GraphQL. Mutations allow us to specify ways to create, update, and delete data. It also provides a way to fetch information after the mutation occurs. In this video, we’ll learn how to create a Mutation Type in GraphQL and specify the information we want returned.

[00:00] We have a GraphQL schema that's exposing a single query type. If we go into graphical to check out the type definitions we can see that the query type exposes two fields, videos and video.

[00:15] Videos, in this case, is just a GraphQL list and it's a GraphQL list of a type called video. Video in this case just has four fields. One is the ID. There's also the title, duration, and whether or not this video was released on Egghead.

[00:34] All this information is great for querying information on our videos, but what if we actually want to go and create new videos to put on our platform? In this case, we would use something called a mutation in GraphQL, so let's go and write one for adding a video to our GraphQL schema.

[00:53] Let's switch on over to our editor of choice and start writing our first mutation. Mutations in GraphQL are just GraphQL object types, so we can create our new root mutation by doing new GraphQL object type. I'm giving it a name of mutation and then the description can be the root mutation type.

[01:17] Next up we'll add a fields object and then inside of that object we'll specify a field called createVideo, which is going to be responsible for creating videos in our GraphQL schema.

[01:30] Each field in a GraphQL mutation also has a type. In this case we're going to have a video type. This is going to correspond to what we're going to be able to query on after we run the mutation.

[01:43] We're also going to need some arguments to help us actually construct our new video. In this case we're just going to specify title for the title of the video, duration for the duration of the video, and finally, release, which will tell us whether or not the video is released to the public.

[02:03] The last part for this mutation is to add in a resolve handler. This has the same signature as those resolve statements from querying, but in this case arguments are going to correspond to the arguments that we created before.

[02:18] The goal of this resolver statement now is to go and take in all of the arguments that are being passed in with this args variable and create our video. Thankfully, I have a method already for that inside of our source/data/index.js file and here there's a method called createVideo.

[02:37] This method takes in a title and duration and released fields for our video, creates a new video with a brand-new ID, pushes it to our end memory array, and then just returns the video. At the end of the file I'm just exporting that method.

[02:54] With this method in hand, we can go back into our index.js file now and import it at the top. I'll just do createVideo here, and now let's go back to our mutation, specifically this resolver. What we can do is just return, createVideo, and then pass in the arguments.

[03:13] CreateVideo takes in an object and the object has the fields title, duration, and release and thankfully that matches up with arcs here, so we'll just pass that in to create our video.

[03:27] Now we've actually created our first mutation type and I'll actually rename our variable here to mutationType just to indicate that. In order to add it to our schema all we need to do is pass it into the mutation field, so mutation and then mutation field.

[03:43] We can verify that this is working by switching into our terminal and rerunning our server by running node index.js. When we switch into graphical and reload the page, we see that there's now a new mutation type available to us inside of our schema.

[04:02] To verify that this mutation actually works for creating new videos, let's go and see what videos currently exist. We'll do videos and then title. We can see that there's a video on creating a GraphQL schema as well as a video on Ember JS CLI.

[04:19] To create our mutation we'll do mutation and we'll give it some kind of name. In this case the name's just going to be m. We'll do createVideo and createVideo takes in a title, which we will say is fu, a duration, which is an integer and we'll say 300.

[04:37] Then finally it takes in a Boolean for a release and we're going to say it's false. Inside of this we actually can query for fields on that resulting video. We'll grab the ID and also the title. Then we'll run our mutation.

[04:55] In the response we can see that we have a new video being created with a given ID and title. We can go and verify that this is added to our list of videos by running our videos query one more time. We'll just get all the titles, one more query, and there we go. Our video was added to our list of videos.

Pieter Malan
Pieter Malan
~ 7 years ago

Great course! I was hoping this course would shed some light on how to handle business rule validations for mutations. Do you have any suggestions for handling custom validation? For example in your case you might not want duplicate items added with the same name. You could throw an exception which would be returned as an error, but this only handles a single validation rule at a time. Anyway do you have any ideas for validations?

Josh Black
Josh Blackinstructor
~ 7 years ago

Hi Ryan! First off, thanks for the watching the course! Hope it's been helpful 😄

I think you bring up a great question, and the answer definitely can stem from where GraphQL sits in your stack. If it's communicating through an API level, passing through the errors that it receives seems like it should be enough.

In your case, I think, when it's talking directly to a Database Layer I think you encounter this situation frequently. In projects that I've worked on, the ORM layer that we talk to directly communicates a set of errors (such as unique constraint violations) and we have a utility to format the set of errors in a friendly manner for client consumers.

In some projects, having resolvers defined outside of the schema might help for this. If you have a VideoResolver, for example, with #create, #update, or #delete methods, then you could point your resolve statements in Mutations towards these resolver methods that communicate to the ORM later and accumulate the set of errors from a given side-effect.

Sorry if this isn't that helpful, unfortunately this definitely can depend on your language runtime for GraphQL as well as the ORMs or Database modules that you're working with.

If you have any more questions, feel free to ask!

Aimn
Aimn
~ 7 years ago

Hi, Thanks for this excellent course. Could you please elaborate on this more. So suppose you have a UserType with firstName (String), lastName (String), age (Number) and suppose you have a mutation to update the user but all data passed to the ORM have errors and the ORM gives you back an object that looks like this: { errors: {firstName: "first name error", lastName: "last name error", age: "age error"} } and I want to pass this to graphql client so that it can show the errors in a form. Can you explain how to pass all the errors back to the client or to graphiql. Thanks

astercraker
astercraker
~ 5 years ago

Great course, I hope the lesson of integration with mongo or mongoatlas

Jeremy
Jeremy
~ 5 years ago

Just wanted to call to your attention that there's a lot of bugs in the transcript for this video:

        title: {
          type: new GraphQLNonNull(GraphQLString),
          description: 'The title of the video.',
        },
        duration: {
          type: new GraphQLNonNull(GraphQLString),
          description: 'The duration of the video (in seconds).',
        },
        released: {
          type: new GraphQLNonNull(GraphQLString),
          description: 'Whether or not the video is released.',
        },
      },

The types here are all GraphQLString instead of String/Int/Boolean respectively.

Down here

Mutation M {
  createVideo(title: "Foo", duration: 300, Boolean: false) {
    id,
    title
  }
}

The field is incorrectly labeled as Boolean instead of released

Md. Anam Hossain
Md. Anam Hossain
~ 5 years ago

When creating a video from mutation I got this error in my terminal. What to do ? DeprecationWarning: Buffer() is deprecated due to security and usability issues. Please use the Buffer.alloc(), Buffer.allocUnsafe(), or Buffer.from() methods instead.

Thanks

Eleonora Lester
Eleonora Lester
~ 5 years ago

When creating a video from mutation I got this error in my terminal. What to do ? DeprecationWarning: Buffer() is deprecated due to security and usability issues. Please use the Buffer.alloc(), Buffer.allocUnsafe(), or Buffer.from() methods instead.

new Buffer.from(title).toString("base64");
Leonel Galán
Leonel Galán
~ 4 years ago

@Eleonora, it should work because it's a deprecation warning, to remove the warning simply use, this is more clear when you visit the documentation for new Buffer(string[, encoding])

Buffer.from(title).toString("base64")
Markdown supported.
Become a member to join the discussionEnroll Today