Server-Side GraphQL in Node.js Arguments & Input Types Exercise
Transcript from the "Arguments & Input Types Exercise" Lesson
>> Scott Moss: So you're gonna create input types for query arguments, you're gonna add arguments for your queries, and you're gonna use arguments in your query filled resolvers to filter data. So let me go over that with you right quick. So if we go back to our schema.js. Right now, you have a pets query, right?
[00:00:25] Everyone should have that, because we did that last exercise. So you're gonna have to add a input for the pets query that allows someone to filter their pets by the properties that exist on a pet, which I would say for now, let's just do a type. Just stick with the type, if you wanna add something fancy, get fancy when it filtered it out but a type is good for now.
[00:00:50] And you also need to create another query for just one pet. So I should be able to have a query that just gets one pet. And maybe it should just be either by an ID, or maybe a name, I'll let you decide how you wanna get one pet, but you need to make a query that gets one pet and it takes an input on how to fetch just that one pet.
[00:01:12] So I'll let you do that, yes?
>> Speaker 2: Are there any rules like, [COUGH] required if? So say you had get pet by ID or by name, but you gotta give me one of them.
>> Scott Moss: So, that's a good question. So, if you have to give me either, or, you won't be able to do that in the SDL, the schema language, cuz you can only say, either you always have to give me that, or you always have to give me that, or you always have to give me both, or you don't have to give me both.
[00:01:39] So, that type of dynamic check, because this is not dynamic, you wrote this as static, you gotta do that in the resolver. In the resolver, you have to check, okay, because my schema, it doesn't have a check on neither of them, but I require one of them, then therefore, you'd have to do that check yourself in the resolver.
>> Speaker 2: Can you throw schema level errors manually like that?
>> Scott Moss: We're gonna get into the errors. Yeah, we're gonna get to the errors but, if you wanna try, throw an error in the resolver and tell me what happens. Yup, just throw it, don't worry about catching it, just throw it.
[00:02:13] See what happens, yes?
>> Speaker 2: Is it considered bad form to go back through the schema?
>> Scott Moss: Yes.
>> Speaker 2: Is it considered bad form to reuse any input-
>> Scott Moss: No.
>> Speaker 2: For more than one query, so using the same input for pets and pet.
>> Scott Moss: No, I think that's smart.
[00:02:31] If it's the same one, then do it. I don't think that's a bad thing, bad idea. I would say as long as they make sense, like if this pet input had some weird strange name that only apply to this pets query and it didn't apply to this one, then maybe change the name or something.
[00:02:47] But no, using the same one, no, it's just as widely accepted as using the same type in many places. So I would say go for it if it works. Cool, yes?
>> Speaker 2: If I want to query by all fields of my type,that means I need to duplicate in the input type?
>> Scott Moss: Yes, you have to be extremely explicit about it. You can't say-
>> Speaker 2: Why can't I reuse as a type, as an input?
>> Scott Moss: You can reuse the types as an input because GraphQL treats types and inputs differently on the AST level. There's different operations they perform on types than they do inputs and mixing the two would complicate the system for them.
[00:03:33] So they specifically asked you to make input types. Now, if you're saying I just want to be able to just to say, come down here and just be like, give me all that pet.fields and something like that, right? Yeah, you can't do that because they want you to be explicit.
[00:03:47] The whole point of this schema is for someone to come in and visually look at it, and be like, okay, I know exactly what this is, it's very explicit. So they don't allow you to do that, even if and when we get to it later, we're gonna get into like, advanced STO features where you can like, have implementations and stuff like that, even then you still have to repeat the fields.
[00:04:09] There's just no way around, at least on the schema level, of easily not repeating those fields. On the client level, we have something called fragments which allow us to avoid that. And you could use fragments on the Schema Definition Language but it's a little different from the fragments you would be using on the client side.
[00:04:30] So if you wanna know more about it, if that's like really a problem for you, I will look into fragments but it's not gonna solve all the problems. Good question though. Yeah, when I learn that, I was like, why? I had a long conversation with the people on Facebook about this, trust me.
[00:04:48] Cool, any questions about that stuff? Okay, so once you have that, then like I said, you need to make that pet query, add some stuff here. And they you need to, one, use your inputs inside your resolver. If you go to the resolvers, there's going to be, when you use the context of models, for instance, ctx.models.pet.
[00:05:19] So in this case, it would be like a findMany. You can just pass any filter object here which are the properties that exist and it'll filter it out for you. So findOne does the same thing. findOne takes an object of fields you wanna filter out and findMany does the same thing.
[00:05:31] So that's done for you, you don't have to worry about that, works just like a regular database REM with, so take note of that. But yeah, you need to update your pets query to do that and you need to create a pet query that also has an input type that does that, yes?
>> Speaker 2: Can a resolver call another resolver?
>> Scott Moss: No.
>> Speaker 2: No, cuz, yeah, promise same definition.
>> Scott Moss: I see what you're saying, it's just the same thing but different method. You have no control in what are these resolvers are called, the client does, that's the whole point. So the only way that you can call another resolver is if you created a function that did this and call them in both places, I would imagine, but you can't because the job of the resolvers is to resolve just one field.
[00:06:13] So, in that case, if you were calling another function, that's not a resolver, that's just something that gets data from somewhere. And that's a good practice. We didn't talk about data sources and things like that. But Apollo has something built into it called a data source which is meant for fetching external APIs but you can use it for just data in your server internally.
[00:06:32] And then that can be responsible for fetching and caching data on an application level, and then you can reuse that logic within the resolvers, and that's the only way. But yeah, resolver doesn't know about another resolver. They don't know what happened before and they don't know what's gonna happen after, and they can't talk to another one.
[00:06:49] So yeah.