Reputation: 7801
I have read both the main "Learn" guide on graphql.com and the howtographql.com tutorial.
I am still struggling with a few concepts, one of them is relating to Arguments.
Basically, I do not understand how GraphQL knows what field of an Object type, a passed argument in a Query type belongs to.
Example:
type Person {
id: ID!
name: String!
age: Int
country: String!
}
type Query PersonsByAge {
person(selectedCountry: String!): [Person]
}
query PersonsByAge {
person(selectedCountry: 'Sweden')
}
Questions
selectedCountry
argument should filter on the country
field?List
as done above?I feel like I am missing something really basic here, I just found that the guides lacked depth and structure.
Thank you.
EDIT:
Fixed parenthesis typo, pointed out in Daniel's answer. Did not fix other syntax issues, to keep the answer matching the question.
Upvotes: 0
Views: 5198
Reputation: 84657
Adding an argument or arguments for a particular field does not impact the value the field resolves to in itself. In GraphQL.js, every field has an associated resolve
function (or "resolver"). It's up to the server to implement that function. The function receives four parameters, including the value of the parent field, the arguments for the field being resolved and the execution context. The resolver can use all or none of these parameters to determine the value that should be resolved for a field.
Yes, GraphQL includes a special collection type called List
that "declares the type of each item in the List". These can be input or output types or scalars. In GraphQL.js, a List is effectively just an array. It's important to note that if a field's type is a List, it's resolver must return an array, and, likewise, if a field's type is an output type, the resolver cannot return an array. GraphQL will not coerce a List
into a non-List
value and vice-versa.
There's a couple of things wrong with your syntax. Your query has an extra parenthesis and no subselection for the person
field (i.e. you don't specify the fields you want returned for that field, which is required since the type for the field is an output type, not a scalar). Additionally, in your schema definition, you've got an extraneous PersonsByAge
label on your Query type which is invalid syntax and not really necessary.
Here's your example, reworked with correct syntax and a resolver to demonstrate the earlier point. This examples assumes you create your schema using graphql-tools
.
const people = [
{ id: 1, name: 'Oscar', country: 'Sweden' },
{ id: 2, name: 'Sal', country: 'Italy' }
]
const typeDefs = `
type Person {
id: ID!
name: String!
country: String!
}
type Query {
person(id: ID!): Person
people(selectedCountry: String!): [Person]
}
`
const resolvers = {
Query: {
person: (root, args, context) => {
// this returns a single object
return people.find(person => person.id === args.id)
},
people: (root, args, context) => {
// this returns an array
return people.filter(person => person.country === args.selectedCountry)
},
},
}
You may then query your schema client-side like this:
query SomeQueryName {
people(selectedCountry: "Sweden") {
id
name
}
}
I highly recommend checking out Apollo Launchpad, which will allow you to create a schema and query it on the fly so you can freely experiment with the syntax and learn by doing.
Upvotes: 4