Skip to content

Commit dd6dc8d

Browse files
author
Sashko Stubailo
authored
Merge pull request #44 from graphql/new-schema
[WIP] New schema for all query/schema examples
2 parents e67270b + 2695016 commit dd6dc8d

File tree

3 files changed

+362
-362
lines changed

3 files changed

+362
-362
lines changed

site/docs/Learn-Queries.md

Lines changed: 15 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -181,36 +181,27 @@ Most discussions of GraphQL focus on data fetching, but any complete data platfo
181181

182182
In REST, any request might end up causing some side-effects on the server, but by convention it's suggested that one doesn't use `GET` requests to modify data. GraphQL is similar - technically any query could be implemented to cause a data write. However, it's useful to establish a convention that any operations that cause writes should be sent explicitly via a mutation.
183183

184-
Here's an example of a simple mutation:
184+
Just like in queries, if the mutation field returns an object type, you can ask for nested fields. This can be useful for fetching the new state of an object after an update. Let's look at a simple example mutation:
185185

186186
```graphql
187-
mutation CreateCharacterInEpisode($name: String!, $appearsIn: Episode!) {
188-
createCharacter(name: $name)
189-
addCharacterToEpisode(name: $name, episode: $appearsIn)
187+
# { "graphiql": true, "variables": { "ep": "JEDI", "review": { "stars": 5, "commentary": "This is a great movie!" } } }
188+
mutation CreateReviewForEpisode($ep: Episode!, $review: ReviewInput!) {
189+
createReview(episode: $ep, review: $review) {
190+
stars
191+
commentary
192+
}
190193
}
191194
```
192195

193-
You can see that a mutation can contain multiple fields, just like a query. There's one important distinction between queries, and mutations, other than the name:
194-
195-
**While query fields are executed in parallel, mutation fields run in series, one after the other.**
196-
197-
This means that even though we sent `createCharacter` and `addCharacterToEpisode` in one request, the first is guaranteed to finish before the second begins, ensuring that we create the character before trying to add it an episode.
196+
In this case, the `incrementCredits` mutation field returns a `Human` object, so we can query the new value of `totalCredits` after giving that character some more credits. Otherwise, we would have needed to send two requests - one to update the credits, and another to get the new value - or guess at the new amount based on outdated data.
198197

199-
#### Returning data from mutations
198+
#### Multiple fields in mutations
200199

201-
Just like in queries, you can ask for nested fields in the mutation result. This can be useful for fetching the new state of an object after an update:
200+
A mutation can contain multiple fields, just like a query. There's one important distinction between queries and mutations, other than the name:
202201

203-
```graphql
204-
mutation IncrementCredits($characterId: ID!) {
205-
incrementCredits(characterId: $characterId) {
206-
totalCredits
207-
}
208-
}
209-
```
210-
211-
In this case, the `incrementCredits` mutation field returns a `Character` object, so we can query the new value of `totalCredits` after giving that character some more credits. Otherwise, we would have needed to send two requests - one to update the credits, and another to get the new value - or guess at the new amount based on outdated data.
202+
**While query fields are executed in parallel, mutation fields run in series, one after the other.**
212203

213-
That's all! Now you know everything you need to know about GraphQL queries and mutations to build a pretty good application. For more advanced features and tips, check out the advanced section.
204+
This means that if we send two `incrementCredits` mutations in one request, the first is guaranteed to finish before the second begins, ensuring that we don't end up with a race condition with ourselves.
214205

215206
### Fragments and type conditions
216207

@@ -226,8 +217,8 @@ query HeroForEpisode($ep: Episode!) {
226217
... on Droid {
227218
primaryFunction
228219
}
229-
... on Droid {
230-
homePlanet
220+
... on Human {
221+
height
231222
}
232223
}
233224
}
@@ -237,4 +228,4 @@ In this query, the `hero` field returns the type `Character`, which might be eit
237228

238229
To ask for a field on the concrete type, you need to use an _inline fragment_ with a type condition. Because the first fragment is labeled as `... on Droid`, the `primaryFunction` field will only be executed if the `Character` returned from `hero` is of the `Droid` type. Similarly for the `homePlanet` field for the `Human` type.
239230

240-
Named fragments can also be used in the same way, since a named fragment always has a type condition attached.
231+
Named fragments can also be used in the same way, since a named fragment always has a type attached.

site/docs/Learn-Schema.md

Lines changed: 48 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ The most basic components of a GraphQL schema are object types, which just repre
4141
```graphql
4242
type Character {
4343
name: String!
44-
appearsIn: [Episode]
44+
appearsIn: [Episode]!
4545
}
4646
```
4747

@@ -55,6 +55,11 @@ The language is pretty readable, but let's go over it so that we can have a shar
5555

5656
Now you know what a GraphQL object type looks like, and how to read the basics of the GraphQL type language.
5757

58+
### Arguments
59+
60+
TODO
61+
- Include the idea of default arguments
62+
5863
### The Query and Mutation types
5964

6065
Most types in your schema will just be normal object types, but there are two types that are special within a schema:
@@ -74,7 +79,7 @@ query {
7479
hero {
7580
name
7681
}
77-
droid(id: "2001") {
82+
droid(id: "2000") {
7883
name
7984
}
8085
}
@@ -155,7 +160,7 @@ Object types, scalars, and enums are the only kinds of types you can define in G
155160
```graphql
156161
type Character {
157162
name: String!
158-
appearsIn: [Episode]
163+
appearsIn: [Episode]!
159164
}
160165
```
161166

@@ -165,7 +170,7 @@ The Non-Null type modifier can also be used when defining arguments for a field,
165170

166171
```graphql
167172
# { "graphiql": true, "variables": { "id": null } }
168-
query DroidById($id: String!) {
173+
query DroidById($id: ID!) {
169174
droid(id: $id) {
170175
name
171176
}
@@ -212,10 +217,10 @@ For example, you could have an interface `Character` that represents any charact
212217

213218
```graphql
214219
interface Character {
215-
id: String!
216-
name: String
220+
id: ID!
221+
name: String!
217222
friends: [Character]
218-
appearsIn: [Episode]
223+
appearsIn: [Episode]!
219224
}
220225
```
221226

@@ -225,25 +230,28 @@ For example, here are some types that might implement `Character`:
225230

226231
```graphql
227232
type Human implements Character {
228-
id: String!
229-
name: String
233+
id: ID!
234+
name: String!
230235
friends: [Character]
231-
appearsIn: [Episode]
232-
homePlanet: String
236+
appearsIn: [Episode]!
237+
starships: [Starship]
238+
totalCredits: Int
233239
}
234240

235241
type Droid implements Character {
236-
id: String!
237-
name: String
242+
id: ID!
243+
name: String!
238244
friends: [Character]
239-
appearsIn: [Episode]
245+
appearsIn: [Episode]!
240246
primaryFunction: String
241247
}
242248
```
243249

244250
You can see that both of these types have all of the fields from the `Character` interface, but also bring in extra fields, `homePlanet` and `primaryFunction`, that are specific to that particular type of character.
245251

246-
Interfaces are useful when you want to return an object or set of objects, but those might be of several different types. For example, in the following query:
252+
Interfaces are useful when you want to return an object or set of objects, but those might be of several different types.
253+
254+
For example, note that the following query produces an error:
247255

248256
```graphql
249257
# { "graphiql": true, "variables": { "ep": "JEDI" } }
@@ -255,7 +263,9 @@ query HeroForEpisode($ep: Episode!) {
255263
}
256264
```
257265

258-
The `hero` field returns the type `Character`, which means it might be either a `Human` or a `Droid` depending on the `episode` argument. In the query above, you can only ask for fields that exist on the `Character` interface, and to ask for a field on a specific object type, you need to use an inline fragment:
266+
The `hero` field returns the type `Character`, which means it might be either a `Human` or a `Droid` depending on the `episode` argument. In the query above, you can only ask for fields that exist on the `Character` interface, which doesn't include `primaryFunction`.
267+
268+
To ask for a field on a specific object type, you need to use an inline fragment:
259269

260270
```graphql
261271
# { "graphiql": true, "variables": { "ep": "JEDI" } }
@@ -275,20 +285,30 @@ Learn more about this in the [inline fragments](XXX) section in the query guide.
275285

276286
Union types are very similar to interfaces, but they don't get to specify any common fields between the types.
277287

278-
XXX no example in SWAPI
279-
280288
```graphql
281-
union SearchResult = Photo | Person
289+
union SearchResult = Human | Droid | Starship
290+
```
282291

283-
type Person {
284-
name: String
285-
age: Int
286-
}
292+
Wherever we return a `SearchResult` type in our schema, we might get a `Human`, a `Droid`, or a `Starship`. Note that members of a union type need to be concrete object types; you can't create a union type out of interfaces or other unions.
287293

288-
type Photo {
289-
height: Int
290-
width: Int
294+
In this case, if you query a field that returns the `SearchResult` union type, you need to use a conditional fragment to be able to query any fields at all:
295+
296+
```graphql
297+
# { "graphiql": true}
298+
{
299+
search(text: "an") {
300+
... on Human {
301+
name
302+
height
303+
}
304+
... on Droid {
305+
name
306+
primaryFunction
307+
}
308+
... on Starship {
309+
name
310+
length
311+
}
312+
}
291313
}
292314
```
293-
294-
In this case, if you query a field that returns the `SearchResult` union type, you need to use a conditional fragment to be able to query any fields at all.

0 commit comments

Comments
 (0)