
GET or POST requests. While GraphQL, in general, introduces some new concepts regarding data organization and interaction, the internal mechanisms of this technology rely on good old HTTP requests.GET request to the endpoint /api/v1/flavors it is expected that it will send a response that looks something like this: [ { "id": 1, "name": "The Lazy Person's Movie Theater", "description": "That elusive flavor that you begrudgingly carted yourself to the theater for, now in the comfort of your own home, you slob!" }, { "id": 2, "name": "What's Wrong With You Caramel", "description": "You're a crazy person that likes sweet popcorn. Congratulations." }, { "id": 3, "name": "Gnarly Chili Lime", "description": "The kind of popcorn you make when you need a good smack in the face."} ] 
description field, but are we going to sit back and pretend that we did not send this field to the client? And what else can we do? And when we, after a few months, are asked about why the application is so slow for users, we will only have to give the manager and no longer meet with the management of the company for which we have made this application.GET or POST requests to transfer data to the client and receive it from it. If we consider this idea in more detail, it turns out that there are two types of queries in GraphQL. The first type includes requests for reading data, which in GraphQL terminology are simply called queries and refer to the letter R (reading, reading) of the acronym CRUD. Requests of the second type are data change requests, which in GraphQL are called mutations. They refer to the books C, U, and D of the CRUD acronym, that is, they use them to create (create), update (update) and delete (delete) entries.https://myapp.com/graphql , in the form of a GET or POST request. We'll talk more about this below. { flavors { name } } { // , . } flavors field. { flavors { // , flavor. } } { flavors { name } } { "data": { "flavors": [ { "name": "The Lazy Person's Movie Theater" }, { "name": "What's Wrong With You Caramel" }, { "name": "Gnarly Chili Lime" } ] } } { flavors { id name description } } { "data": { "flavors": [ { "id": 1, "name": "The Lazy Person's Movie Theater", description: "That elusive flavor that you begrudgingly carted yourself to the theater for, now in the comfort of your own home, you slob!" }, { "id": 2, "name": "What's Wrong With You Caramel", description: "You're a crazy person that likes sweet popcorn. Congratulations." }, { "id": 3, "name": "Gnarly Chili Lime", description: "A friend told me this would taste good. It didn't. It burned my kernels. I haven't had the heart to tell him." } ] } } flavor , then we can take advantage of the fact that GraphQL can work with arguments: { flavors(id: "1") { id name description } } id ) of the object, information about which we need, but in such cases we can use dynamic identifiers: query getFlavor($id: ID) { flavors(id: $id) { id name description } } getFlavor can replace getFlavor with something like pizza , and the request remains operable) and declare the variables that the request expects. In this case, it is assumed that the request will be given an identifier ( id ) of a scalar type ID (we will talk about types below).id used when executing a query, this is how the response to such a query will look like: { "data": { "flavors": [ { "id": 1, "name": "The Lazy Person's Movie Theater", description: "That elusive flavor that you begrudgingly carted yourself to the theater for, now in the comfort of your own home, you slob!" } ] } } nutrition that contains information about the nutritional value of different types of popcorn: { flavors { id name nutrition { calories fat sodium } } } flavor object will contain an embedded nutrition object. But it is not so. Using GraphQL, you can combine calls to independent, but related data sources in a single query, which allows you to get answers that make it easy to work with nested data without the need to denormalize the database: { "data": { "flavors": [ { "id": 1, "name": "The Lazy Person's Movie Theater", "nutrition": { "calories": 500, "fat": 12, "sodium": 1000 } }, ... ] } } mutation updateFlavor($id: ID!, $name: String, $description: String) { updateFlavor(id: $id, name: $name, description: $description) { id name description } } updateFlavor mutation, specifying some variables - id , name and description . Acting on the same scheme that is used in the description of requests, we “decorate” the variable fields (root mutation) using the keyword mutation , followed by the name describing the mutation, and the set of variables that are needed to form the corresponding data change request.id , name and description fields. This can come in handy when developing something like optimistic interfaces, eliminating the need to fulfill a request to get changed data after changing it. import express from 'express' import graphqlHTTP from 'express-graphql' import schema from './schema' const app = express() app.use('/graphql', graphqlHTTP({ schema: schema, graphiql: true })) app.listen(4000) graphqlHTTP function from the express-graphql from Facebook, we “attach” the scheme (assuming that it is described in a separate file) and start the server on port 4000. That is, clients, if we talk about local use of this server, will be able to send requests over address http://localhost:4000/graphql . import gql from 'graphql-tag' import mongodb from '/path/to/mongodb' // - . , `mongodb` MongoDB. const schema = { typeDefs: gql` type Nutrition { flavorId: ID calories: Int fat: Int sodium: Int } type Flavor { id: ID name: String description: String nutrition: Nutrition } type Query { flavors(id: ID): [Flavor] } type Mutation { updateFlavor(id: ID!, name: String, description: String): Flavor } `, resolvers: { Query: { flavors: (parent, args) => { // , args , { id: '1' } return mongodb.collection('flavors').find(args).toArray() }, }, Mutation: { updateFlavor: (parent, args) => { // , args { id: '1', name: 'Movie Theater Clone', description: 'Bring the movie theater taste home!' } // . mongodb.collection('flavors').update(args) // flavor . return mongodb.collection('flavors').findOne(args.id) }, }, Flavor: { nutrition: (parent) => { return mongodb.collection('nutrition').findOne({ flavorId: parent.id, }) } }, }, } export default schema typeDefs ) and resolvers ( resolver ). The typeDefs contains type declarations for the data used in the application. For example, earlier we talked about a request to get a list of flavor objects from the server. In order for our server to perform a similar request, you need to do the following three steps:flavor objects look (in the example above, this looks like a type declaration of type Flavor ).type Query field type Query (this is the flavors property of type Query ).resolvers.Query function-resolvers.Query object, written in accordance with the fields declared in the type Query root field.typeDefs . Here we give the scheme information about the shape (shape) of our data. In other words, we are telling GraphQL about various properties that may be contained in entities of the corresponding type. type Flavor { id: ID name: String description: String nutrition: Nutrition } type Flavor declaration indicates that the flavor object may contain an id field of type ID , a name field of type String , a description field of type String and a nutrition field of type Nutrition .nutrition we use the name of another type declared in typeDefs . Here, the type Nutrition design describes the nutritional form of popcorn.type Flavor declaration, here we specify the names of the fields that will be contained in the nutrition objects, using, as the data types of these fields (properties), what in GraphQL is called scalar data types. At the time of this writing, GraphQL supported 5 built-in scalar data types :Int : 32-bit integer with a sign.Float : A double-precision floating-point number with a sign.String : a sequence of characters encoded in UTF-8.Boolean : boolean true or false .ID : a unique identifier often used to load objects multiple times or as a key in the cache. Values ​​of type ID serialized in the same way as strings, but the indication that an ID type has a certain value underlines the fact that this value is not intended to be shown to people, but for use in programs.nutrition property described in the type Flavor design, the Nutrition type. type Query { flavors(id: ID): [Flavor] } type Query construction, which describes the root type of the Query (the “root query” that we talked about earlier), we declare the name of the field that can be queried. When declaring this field, we, along with the data type that we expect to return, specify the arguments that can be received in the request.id argument of a scalar type ID . In response to such a request, an array of objects is expected whose device resembles a Flavor device.type Query has a definition of a field , we need to describe what is called a resolver function.resolvers , Query , , flavors , . flavors , type Query . typeDefs: gql`…`, resolvers: { Query: { flavors: (parent, args) => { // , args { id: '1' } return mongodb.collection('flavors').find(args).toArray() }, }, … }, parent — , , args , . context , . «» ( — , ).flavors MongoDB, args ( ) .find() , , .nutrition . , , Nutrition , , , , flavor . , / .type Flavor nutrition type Nutrition , . , , flavor . typeDefs: gql` type Nutrition { flavorId: ID calories: Int fat: Int sodium: Int } type Flavor { […] nutrition: Nutrition } type Query {…} type Mutation {…} `, resolvers: { Query: { flavors: (parent, args) => {…}, }, Mutation: {…}, Flavor: { nutrition: (parent) => { return mongodb.collection('nutrition').findOne({ flavorId: parent.id, }) } }, }, resolvers , , Query , Mutation Flavor . , typeDefs .Flavors , , nutrition -. , Flavor . , : « , nutrition , type Flavor ».parent , -. , parent , , , flavors . , flavor , : { flavors { id name nutrition { calories } } } flavor , flavors , nutrition , parent . , , , MongoDB, parent.id , id flavor , .parent.id , nutrition flavorId , flavor .type Mutation , , updateFlavor , , . type Mutation { updateFlavor(id: ID!, name: String, description: String): Flavor } updateFlavor id ID ( , ! , GraphQL , ), name String description String ». , , Flavor ( — , id , name , description , , , nutrition ). { typeDefs: gql`…`, resolvers: { Mutation: { updateFlavor: (parent, args) => { // , args { id: '1', name: 'Movie Theater Clone', description: 'Bring the movie theater taste home!' } // . mongodb.collection('flavors').update( { id: args.id }, { $set: { ...args, }, }, ) // flavor . return mongodb.collection('flavors').findOne(args.id) }, }, }, } updateFlavor , : , , — , flavor .flavor . Why is this so?flavor , .args ? , . , , , 100% , . , , , , , .graphql ( express-graphql , ) — . , GraphQL - . , -, , , , .
Source: https://habr.com/ru/post/445268/
All Articles