REST & GraphQL API Design in Node.js, v2 (using Express & MongoDB) Queries and Mutations Walkthrough
This course has been updated! We now recommend you take the API Design in Node.js, v4 course.
Transcript from the "Queries and Mutations Walkthrough" Lesson
>> Scott Moss: All right, so, before we hop in the challenge, I'm just gonna walk through some GraphQL stuff so we can actually explore and see what's going on. Okay, so what you're looking at here, who seen this before? Okay. So this is called GraphiQL, it's like a play on words, it's GraphiQL, they threw an I in there, graphical, it's pretty funny.
[00:00:27] But basically this is, remember I said GraphQL has interactive docs? This is it. This is GraphQL's interactive docs. So this is actually the API, the graph API, the GraphiQL API that you'll be building today. This is on the last solution bands and I just have it pulled up.
[00:00:42] And with this what we can do is we can actually explore GraphQL and we can see a couple things. So I'm gonna give you a tour right quick. So what we have here on the left is where we can write our GraphQL quiries and mutations and we're gonna do that in just a second.
[00:00:55] Over here on the right we have the results of those queries and mutations. So when you execute them, the results that the server responds with will be printed here on the right. Down below, if you drag this up, we have a little place where we can inject variables into our queries and mutations.
[00:01:11] And variables are things that you will need to do. For instance, you wanna do filtering, you would put that in a variable. If you needed to pass an ID because you wanted to get this song by this ID, you would put that in a variable. Things that are dynamic, they have to be injected into your queries.
[00:01:24] Those are variables. Up here we have this play button which executes the query. This prettify button just prettifies your query, so it's like nice and formatted. History allows you to go back. And then the best part is this Docs tab over here. So click on Docs. Most likely or most depending on what type of GraphQL API you're looking at.
[00:01:44] You're either gonna see query and mutation or you're gonna see root. In our example we're gonna see query and mutation because we are not doing what's called a relay based GraphQL API. Relay is a framework that Facebook made in conjunction with GraphQL. It's a client side GraphQL implementation that implements GraphQL slightly differently using edges and nodes like a true graph.
[00:02:07] We're not gonna do that. We're just gonna keep it simple with a GraphQL API. So you'll see query mutations. So these are the roots. So remember what I said queries are? Anybody remember?
>> Speaker 2: They get data.
>> Scott Moss: They get data. So in our case, get one, get all, right?
[00:02:21] So I click on query, you'll see these functions here that like mean absolutely nothing to you right now. But let's read through the syntax and try to figure out what's going on. So let's look at this first one, it says get me. And then, it's got this semicolon, and user with an exclamation.
[00:02:37] Basically what this is saying is, hey, if you click on query, you have a query, its name is called get me. And its return value is a user type. And this exclamation, this bang here, is saying it's non-null. It cannot be null. If there is no user, it's probably gonna throw an error.
[00:02:56] It's never gonna return a null user, that's never gonna be null. It's either gonna be a user or it's gonna throw an error. It's never gonna be empty, that's what that's saying. So that's the syntax for this. So if you go down to the next one, this one is called song and you see these parenthesis there.
[00:03:09] You probably guessed, these are the arguments that it takes. It takes an argument called ID and its type is an ID type and that then means that it's required. It's a required argument. You have to pass it in and its return type is the song which is also non-null, right.
[00:03:28] Down here below in the next one, allSongs is a function. It returns an array of songs, and that array is now null. So there might not be any songs in the array, but there will always be an array. That's what that's saying. There will always be an array, even if there might not be anything in it.
[00:03:44] If I wanted to say that I want there always to be a song, I could have put a bang after the G in song, which means it's going to be a non null array, and there will always be something in it. But, that's not the case.
>> Scott Moss: Any questions on that stuff?
>> Speaker 3: So, the non null, you said if there's an error. How is that actually handled?
>> Scott Moss: So, the way the non null works is, when you resolve these data types for GraphQL and it goes back through GraphQL before it goes to the client GraphQL will see, it'll look at the thing you gave it, and it'll be like, based on the schema, this thing can be non null.
[00:04:21] You gave me back a null value, so it'll break. It'll break right there, and the client will get an error and say cannot have non null value for user. And the server will get an error with the same thing. So that's one way it'll break. The other way is, you actually throw the error yourself inside of your resolver.
[00:04:37] So you can say hey, I went to go get me, but I could not get me, so I'm just gonna throw an error right quick. So it's totally up to you how you wanna do it. You can let GraphQL handle that non null error for you, or you can catch the error yourself on the resolver and throw a more descriptive error to the client.
[00:04:55] But yeah, by default, if you return a null value for a non null type, GraphQL will break. Anymore questions on this stuff? We're gonna keep going. All right, so let's use one of these. So let's say I wanna do a query on getMe. Let's first see what a user is.
[00:05:19] So if click on user, you can see that here all the properties of a user, right? Now the user type was not built into GraphQL. GraphQL out just like any language out there has primitive types or what they call in GraphQL scholar types. Scholar types are ttypes that are built into GraphQL.
[00:05:36] And those types are very basic, you can pretty much use them in almost any language. You have strings, you have integers, floats, IDs, and booleans. And then you have enums, which are just constants, right? So those are all primitive types in GraphQL. Anything else that's not that, is a type that we made.
[00:05:59] So this user type, we made that type. This song type, we made that type. This playlist type, we made that. ID, that's a scholar type, that's built in. So the way GraphQL works is whenever you try to resolve a type that is non-scholar, you have to manually return that, you have to manually create that type.
[00:06:17] Anything that is scalar, is resolved automatically for you because it's just a value. If it's non-scalar, this basically means it's an object. Everything that's non-scalar like users, song, playlist, that's an object and you have to describe the shape of that object. So in our case, we said a user looks like this.
[00:06:33] It has an ID, a username, an array of playlists. Created an updated app, right? So that's how we describe the shape of the user. We're all gonna do this. So this is like, so if you're like, I can't follow along right now, that's totally fine, I'm just giving you some context so that we can actually start working on it.
[00:06:51] So let's do a query request, let's jump right into it. There's two ways to do a query, well there's a couple of ways to do a query and depending on what your needs are. Our needs are just to check it out, so the way we're gonna do it first is we're just gonna use this empty object like this.
[00:07:05] Most things in GraphQL start off using this syntax unless you do names, query, or mutations. And then, we follow it by the name of the query we wanna do. So in this case I wanna do getMe. And you see, I get some autocomplete there. So I'll hit Enter.
[00:07:19] That'll do the getMe query. And because getMe returns a non-scholar type, which is user, and we said if it's not scholar it's an object, we have to tell GraphQL what properties on that object do we want back? So if we just ran this right now, I think by default, GraphiQL will automatically stick in the ID property for us by default.
[00:07:41] But most clients won't do that. So now we have to say cool, run the getMe query and then from that I wanna get the ID property of the user and you can see it auto completed. Also I wanna get the username property from the query.and it also auto completed that.
[00:07:56] Then I can hit Play or hit Cmd+Enter and I can execute. And I get an error because we haven't implemented this on our server yet. So this would go and fetch the current user that's signed in with the JSON web token and actually get that user. But you can see here the format that it responds, if we were to get data you see data right here.
[00:08:18] And this would be your query with the data but if you have an error, this is how it responds. This is very unlike REST because the way REST works is, you kind of look at the status codes for the error. So you're like, it's a 401, it's a 403.
[00:08:33] You don't get status codes, you probably just get back a 200 almost every time. And then you've just got to look at the errors object. So it completely changes how you would handle errors. So I mean it's totally up to you as well. You can totally set back the headers, and stuff like that if you want.
[00:08:48] But GraphQL uses this errors properties here to determine what errors to send back, and stuff like that. All right, so let's try another query here. Let's try to do the all songs query here. So we'll say that. We'll say all songs. You can see it auto completes. All songs doesn't take any arguments, so I can go ahead and get the properties that I want on all songs.
[00:09:09] All songs returns an array of all songs. So if I go look at a song, what does a song have? It has an ID, a title, a URL, an album. Cool. Let me get the ID of that. Let me get the URL. And I'll also get the title and I can run that.
[00:09:23] And because I don't have any songs on the server, it just sends back an array of nothing, because we don't have any songs. We actually have to create some songs. So you can see here we get back a data property. And then this name right here allSongs, that name is generated because that's the name of the query that we executed.
[00:09:41] So it's data.allSongs. If we don't want it to say all songs, we can actually alias this and we can say you know what? Just call it songs. And the way you do that is you just put the alias that you want with a semicolon in front of the query.
[00:09:54] And now when you run it, you can see now it just says songs. I think that's something so simple but yet very powerful. This allows you to like get data from your server and immediately pass it into your client without doing a lot of transformations. Depending on who implemented your server and how they did it.
[00:10:10] So, let's actually create some songs so we can query this. So the next thing we'll do is we'll do a mutation. And mutations are a little different. You need to use the mutation keyword here. And then this name right here, you give it a name, because what you need to do is, you can save these mutations, you can save these queries on your client.
[00:10:30] And most clients used names to reference them. So this name that I'm about to give it, you can give it whatever you want. The convention is to use title case. So I'm just gonna call this, CreateSong. I was gonna call it CreateSong, but you can call it whatever you want.
[00:10:46] This is not a strict typing thing. And then you have to describe if any arguments what those arguments would be. And because it's a mutation most likely you'd probably have some arguments. So the way that works is you use this dollar sign like this. This dollar sign means I'm making a variable.
[00:11:01] It's a placeholder for a variable. And I will say this create song and actually, let's go look at the mutation here. We can go look at the mutation and we can say, new song right there. It takes the argument called input and its type is newSong. NewSong is not a scholar type.
[00:11:17] We talked about the six scholar types, newSong is not one of those, that means it's an object. If it's not a scholar type, it's probably an object. So, newSong, we can click on that to see what that is. It takes a title or URL or album or artist or rating or favorite.
[00:11:31] None of them are required. So let's just do that. So we'll say, this takes input. Its type is right here, NewSong! with an exclamation. So we must satisfy that. We'll say NewSong! with an exclamation. And then now this is where we actually run our mutation. And the mutation is called NewSong!
[00:11:57] So we'll say newSong, and it takes in an input whose value is that dollar input variable. That gives us the newSong. And because newSong, the actual mutation, returns a song type, we can describe what properties we want back. So I'm gonna say I want back the ID, I want back the title, and I want back the URL.
[00:12:21] So I'm gonna do that. And then down below it, now I have to pass in this input object, with the variables. So down here I'll say, cool, I need a variable called input, and auto complete it for me. And we know that input is type newSong. So if we go look at that, you'll see that it needs to have some of this.
[00:12:41] So I'm gonna give it a title, you'll see it auto completed and like dance, dance is the name. And then I'll also gonna give it a URL to the song.
>> Scott Moss: I was gonna just put something here.
>> Scott Moss: Cool. And then I'm also gonna give it an artist.
>> Scott Moss: Cool. So we got that, we got the input. It satisfies the type of newSong. We bound it to the input variable in the mutation. We expanded on the return type and asked for an ID and a title URL. And now we can go ahead and try this mutation.
[00:13:29] I'm actually not sure if this is on the branch that I'm on if it is actually created or not, but let's run it. And yeah it is. So we got back the results of a new mutation, we created a new song here. So now we have the new song, here's the ID we get back because I asked for the ID, here's the title we get back that I created, and here's the URL that we get back.
[00:13:52] So now if I go back up to this query above and initiate the songs again. I should get back at least one song. And there it is.
>> Scott Moss: And if I don't wanna get the title, I don't have to get the title, it's gone. You can ask for it the way you want it.
>> Scott Moss: That was a quick walk through for some of the stuff we'll do in GraphQL. So now that you have some context we're gonna go in and we're actually gonna start building this. So you're not expected to remember any of the stuff that I just showed you. I just wanted you to have some context that way you're not just swimming in the dark.
[00:14:26] Any questions on this stuff? Who here is excited about GraphQL so far? Okay, all right. Yeah. Once I saw this, I was just like why would anybody use REST ever again. This is so much better, it's almost magical! Then I built, I remember the first time I built a GraphQL server from the back end.
[00:14:47] I was like, okay, now I get it. This is still pretty magical.