graphql_GraphQL简介:它如何工作以及如何使用

graphql

GraphQL is a query language for API’s. It shows what are the different types of data provided by the server and then the client can pick exactly what it wants.

GraphQL是API的查询语言。 它显示了服务器提供的不同类型的数据,然后客户端可以准确选择所需的数据。

Also in GraphQL you can get multiple server resources in one call rather than making multiple REST API calls.

同样在GraphQL中,您可以在一次调用中获得多个服务器资源,而不是进行多个REST API调用。

You can check out https://graphql.org/ for the full list of benefits.

您可以查看https://graphql.org/以获得全部好处列表。

The thing is until you see GraphQL in action, it’s hard to understand the benefits. So let’s get started with using GraphQL.

问题是直到您看到GraphQL发挥作用,才很难理解其好处。 因此,让我们开始使用GraphQL。

We will be using GraphQL along with NodeJS in this article.

我们将在本文中将GraphQL和NodeJS一起使用。

先决条件 (Pre-requisites)

Install NodeJS from here: https://nodejs.org/en/.

从此处安装NodeJS: https : //nodejs.org/en/

如何将GraphQL与NodeJ一起使用 (How to use GraphQL with NodeJs)

GraphQL can be used with multiple languages. Here we will focus on how we can use GraphQL with JavaScript using NodeJS.

GraphQL可以与多种语言一起使用。 在这里,我们将重点介绍如何使用NodeJS将GraphQL与JavaScript结合使用。

Create a Folder called graphql-with-nodejs. Go into the project folder and run npm init to create the NodeJS project. The command for this is given below.

创建一个名为graphql-with-nodejs的文件夹。 进入项目文件夹并运行npm init来创建NodeJS项目。 下面给出了此命令。

cd graphql-with-nodejs npm init

安装依赖项 (Install the Dependencies)

Install Express using the following command:

使用以下命令安装Express:

npm install express

Install GraphQL using the following command. We will be installing GraphQL and GraphQL for Express.

使用以下命令安装GraphQL。 我们将安装GraphQL和GraphQL for Express。

npm install express-graphql graphql

NodeJS代码 (NodeJS Code)

Create a file called server.js inside the project and copy the following code into it:

在项目内部创建一个名为server.js的文件,并将以下代码复制到其中:

const express = require('express');
const port = 5000;
const app = express();

app.get('/hello', (req,res) => {
    res.send("hello");
   }
);

app.listen(port);
console.log(`Server Running at localhost:${port}`);

The above code has a single HTTP GET endpoint called /hello.

上面的代码只有一个HTTP GET端点/ hello

The end point is created using Express.

终点是使用Express创建的。

Now let us modify this code to enable GraphQL.

现在让我们修改此代码以启用GraphQL。

在代码中启用GraphQL (Enabling GraphQL in the code)

GraphQL will have a single URL endpoint called /graphql which will handle all requests.

GraphQL将具有一个名为/ graphql的 URL端点,该端点将处理所有请求。

Copy the following code into server.js:

将以下代码复制到server.js中:

//get all the libraries needed
const express = require('express');
const graphqlHTTP = require('express-graphql');
const {GraphQLSchema} = require('graphql');

const {queryType} = require('./query.js');

//setting up the port number and express app
const port = 5000;
const app = express();

 // Define the Schema
const schema = new GraphQLSchema({ query: queryType });

//Setup the nodejs GraphQL server
app.use('/graphql', graphqlHTTP({
    schema: schema,
    graphiql: true,
}));

app.listen(port);
console.log(`GraphQL Server Running at localhost:${port}`);

Let us go through this code now.

现在让我们来看一下这段代码。

graphqlHTTP enables us to set up a GraphQL server at /graphql url. It knows how to handle the request that is coming in.

graphqlHTTP使我们能够在/ graphql URL处设置GraphQL服务器。 它知道如何处理即将到来的请求。

This setup is done in the following lines of code:

此设置通过以下代码行完成:

app.use('/graphql', graphqlHTTP({
    schema: schema,
    graphiql: true,
}));

Now let us explore the parameters inside graphqlHTTP.

现在让我们探索graphqlHTTP内部的参数。

石墨烯 (graphiql)

graphiql is a Web UI with which you can test the GraphQL endpoints. We will set this to true so that it is easier to test the various GraphQL endpoints we create.

graphiql是一个Web UI,可用于测试GraphQL端点。 我们将其设置为true,以便更轻松地测试我们创建的各种GraphQL端点。

图式 (schema)

GraphQL has only one external endpoint /graphql. This endpoint can have multiple other endpoints doing various things. These endpoints would be specified in the schema.

GraphQL只有一个外部端点/ graphql 。 这个端点可以有多个其他端点来做各种事情。 这些端点将在模式中指定。

The schema would do things like:

该模式将执行以下操作:

  • Specify the endpoints

    指定端点
  • Indicate the input and output fields for the endpoint

    指示端点的输入和输出字段
  • Indicate what action should be done when an endpoint is hit and so on.

    指示在命中端点时应采取的措施等。

The Schema is defined as follows in the code:

该模式在代码中的定义如下:

const schema = new GraphQLSchema({ query: queryType });

The schema can contain query as well as mutation types. This article will focus only on the query type.

该模式可以包含查询以及变异类型。 本文仅关注查询类型。

询问 (query)

You can see in the schema that the query has been set to queryType.

您可以在模式中看到查询已设置为queryType

We import queryType from query.js file using the following command:

我们使用以下命令从query.js文件导入queryType:

const {queryType} = require('./query.js');

query.js is a custom file which we will be creating soon.

query.js是一个自定义文件,我们将很快创建它。

query is where we specify the read-only endpoints in a schema.

查询是我们在架构中指定只读端点的位置。

Create a file called as query.js in the project and copy the following code into it.

在项目中创建一个名为query.js的文件,并将以下代码复制到其中。

const { GraphQLObjectType,
    GraphQLString
} = require('graphql');


//Define the Query
const queryType = new GraphQLObjectType({
    name: 'Query',
    fields: {
        hello: {
            type: GraphQLString,

            resolve: function () {
                return "Hello World";
            }
        }
    }
});

exports.queryType = queryType;

查询说明 (query Explained)

queryType is created as a GraphQLObjectType and given the name Query.

queryType创建为GraphQLObjectType,并命名为Query

fields are where we specify the various endpoints.

字段是我们指定各种端点的位置。

So here we are adding one endpoint called hello.

因此,在这里我们添加了一个称为hello的端点

hello has a type of GraphQLString which means this endpoint has a return type of String. The type is GraphQLString instead of String since this a GraphQL schema. So directly using String will not work.

hello具有GraphQLString类型 ,这意味着此端点的返回类型为String。 类型是GraphQLString而不是String,因为这是GraphQL模式。 因此,直接使用String是行不通的。

resolve function indicates the action to be done when the endpoint is called. Here the action is to return a String “Hello World”.

resolve函数指示调用端点时要执行的操作。 此处的操作是返回字符串“ Hello World”。

Finally, we export the querytype using exports.queryType = queryType. This is to ensure we can import it in server.js.

最后,我们使用exports.queryType = queryType导出查询exports.queryType = queryType 。 这是为了确保我们可以将其导入到server.js中。

运行应用程序 (Running the Application)

Run the application using the following command:

使用以下命令运行应用程序:

node server.js

The application runs on localhost:5000/graphql.

该应用程序在localhost:5000 / graphql上运行。

You can test the application by going to localhost:5000/graphql.

您可以通过转到localhost:5000 / graphql来测试应用程序。

This URL runs the Graphiql web UI as shown in the screen below.

该URL运行Graphiql Web UI,如下屏幕所示。

The input is given in the left and the output is shown in the right.

输入在左侧,输出在右侧。

Give the following input

输入以下内容

{
  hello
}

This will give the following output

这将给出以下输出

{
  "data": {
    "hello": "Hello World"
  }
}

恭喜😊 (Congrats 😊)

You have created your first GraphQL endpoint.

您已经创建了第一个GraphQL端点。

添加更多端点 (Adding more endpoints)

We will create 2 new endpoints:

我们将创建2个新端点:

  • movie: This endpoint will return a movie, given the movie ID

    movie :给定电影ID,此端点将返回电影

  • director: This endpoint will return a director given the director ID. It will also return all the movies directed by this director.

    导演 :此端点将返回给定导演ID的导演。 它还将返回由该导演执导的所有电影。

新增资料 (Adding Data)

Usually, an application will read data from a Database. But for this tutorial, we will be hardcoding the data in the code itself for simplicity.

通常,应用程序将从数据库读取数据。 但是对于本教程,为简单起见,我们将在代码本身中对数据进行硬编码。

Create a file called data.js and add the following code.

创建一个名为data.js的文件,并添加以下代码。

//Hardcode some data for movies and directors
let movies = [{
    id: 1,
    name: "Movie 1",
    year: 2018,
    directorId: 1
},
{
    id: 2,
    name: "Movie 2",
    year: 2017,
    directorId: 1
},
{
    id: 3,
    name: "Movie 3",
    year: 2016,
    directorId: 3
}
];

let directors = [{
    id: 1,
    name: "Director 1",
    age: 20
},
{
    id: 2,
    name: "Director 2",
    age: 30
},
{
    id: 3,
    name: "Director 3",
    age: 40
}
];

exports.movies = movies;
exports.directors = directors;

This file has the movies and directors data. We will be using the data in this file for our endpoints.

此文件包含电影和导演数据。 我们将使用此文件中的数据作为端点。

将电影端点添加到查询 (Adding the movie endpoint to the query)

The new endpoints will be added to queryType in query.js file.

新的端点将添加到query.js文件中的queryType中。

The code for the movie endpoint is shown below:

电影端点的代码如下所示:

movie: {
            type: movieType,
            args: {
                id: { type: GraphQLInt }
            },
            resolve: function (source, args) {
                return _.find(movies, { id: args.id });
            }
        }

The return type of this endpoint is movieType which will be defined soon.

该端点的返回类型是movieType ,将很快定义。

args parameter is used to indicate the input to the movie endpoint. The input to this endpoint is id which is of type GraphQLInt.

args参数用于指示影片端点的输入。 此端点的输入是id ,其类型为GraphQLInt。

resolve function returns the movie corresponding to the id, from the movies list. find is a function from lodash library used to find an element in a list.

resolve函数从电影列表中返回与id对应的电影。 findlodash库中的一个函数,用于在列表中查找元素。

The complete code for query.js is shown below:

query.js的完整代码如下所示:

const { GraphQLObjectType,
    GraphQLString,
    GraphQLInt
} = require('graphql');
const _ = require('lodash');

const {movieType} = require('./types.js');
let {movies} = require('./data.js');


//Define the Query
const queryType = new GraphQLObjectType({
    name: 'Query',
    fields: {
        hello: {
            type: GraphQLString,

            resolve: function () {
                return "Hello World";
            }
        },

        movie: {
            type: movieType,
            args: {
                id: { type: GraphQLInt }
            },
            resolve: function (source, args) {
                return _.find(movies, { id: args.id });
            }
        }
    }
});

exports.queryType = queryType;

From the above code, we can see that movieType is actually defined in types.js.

从上面的代码中,我们可以看到movieType实际上是在types.js中定义的

添加自定义类型movieType (Adding the Custom Type movieType)

Create a file called types.js.

创建一个名为types.js的文件。

Add the following code into types.js

将以下代码添加到types.js中

const {
    GraphQLObjectType,
    GraphQLID,
    GraphQLString,
    GraphQLInt
} = require('graphql');

// Define Movie Type
movieType = new GraphQLObjectType({
    name: 'Movie',
    fields: {
        id: { type: GraphQLID },
        name: { type: GraphQLString },
        year: { type: GraphQLInt },
        directorId: { type: GraphQLID }

    }
});

exports.movieType = movieType;

It can be seen that movieType is created as a GraphQLObjectType.

可以看出, movieType是作为GraphQLObjectType创建的

It has 4 fields: id, name, year and directorId. The types for each of these fields are specified as well while adding them.

它具有4个字段: id,name,year和directorId 。 在添加它们时,还要指定每个字段的类型。

These fields come directly from the data. In this case, it will be from movies list.

这些字段直接来自数据。 在这种情况下,它将来自电影列表。

添加主管端点的查询和类型 (Adding the query and type for director endpoint)

Like movie, even the director endpoint can be added.

就像电影一样,甚至可以添加导演端点。

In query.js, the director endpoint can be added as follows:

query.js中 ,可以按以下方式添加Director端点:

director: {
            type: directorType,
            args: {
                id: { type: GraphQLInt }
            },
            resolve: function (source, args) {
                return _.find(directors, { id: args.id });
            }
        }

directorType can be added as follows in types.js:

directorType可以在types.js中添加如下

//Define Director Type
directorType = new GraphQLObjectType({
    name: 'Director',
    fields: {
        id: { type: GraphQLID },
        name: { type: GraphQLString },
        age: { type: GraphQLInt },
        movies: {
            type: new GraphQLList(movieType),
            resolve(source, args) {
                return _.filter(movies, { directorId: source.id });
            }

        }

    }
});

Wait a minute. The directorType is slightly different from movieType. Why is this?

等一下。 DirectorTypemovieType略有不同。 为什么是这样?

Why is there a resolve function inside directorType? Previously we saw that resolve functions were present only in the query…

为什么DirectorType中有一个resolve函数 以前我们看到解析函数仅存在于查询中……

DirectorType的特殊性质 (The special nature of directorType)

When the director endpoint is called we have to return the director details, as well as all the movies the director has directed.

调用导演端点时,我们必须返回导演详细信息以及导演执导的所有电影。

The first 3 fields id, name, age in directorType are straightforward and come directly from the data (directors list).

DirectorType中的前3个字段ID,名称,年龄很简单,直接来自数据( Directors列表)。

The fourth field, movies, needs to contain the list of movies by this director.

电影的第四个字段需要包含该导演的电影列表。

For this, we are mentioning that the type of movies field is a GraphQLList of movieType (List of movies).

为此,我们提到电影的类型字段是movieType的GraphQLList (电影列表)。

But how exactly will we find all the movies directed by this director?

但是,我们究竟如何找到这位导演执导的所有电影呢?

For this, we have a resolve function inside the movies field. The inputs to this resolve function are source and args.

为此,我们在“电影”字段中具有“ 解析”功能。 此resolve函数的输入是sourceargs

source will have the parent object details.

源将具有父对象详细信息。

Lets say the fields id =1, name = “Random” and age = 20 for a director. Then source.id =1, source.name = “Random” and source.age = 20

假设一个字段的ID为= 1,名称为“ Random”,年龄为20 。 然后source.id = 1,source.name =“随机”,source.age = 20

So in this example, resolve function finds out all the movies where directorId matches the Id of the required Director.

因此,在此示例中,解决功能会找出所有DirectorId与所需Director的ID相匹配的电影。

(Code)

The Entire code for this application is available in this GitHub repo

该应用程序的完整代码可在此GitHub存储库中找到

测试应用 (Testing the Application)

Now let us test the application for different scenarios.

现在让我们针对不同的场景测试应用程序。

Run the application using node server.js.

使用node server.js运行应用程序。

Go to localhost:5000/graphql and try the following inputs.

转到localhost:5000 / graphql并尝试以下输入。

电影 (movie)

Input:

输入:

{
  movie(id: 1) {
    name
  }
}

Output:

输出:

{
  "data": {
    "movie": {
      "name": "Movie 1"
    }
  }
}

From the above, we can see that the client can request exactly what it wants and GraphQL will ensure only those parameters are sent back. Here only name field is requested and only that is sent back by the server.

从上面的内容中,我们可以看到客户端可以准确地请求其所需的内容,而GraphQL将确保仅将这些参数发送回去。 此处仅请求名称字段,并且仅由服务器发送回该名称字段。

In movie(id: 1), id is the input parameter. We are asking the server to send back the movie which has an id of 1.

movie(id: 1) ,id是输入参数。 我们要求服务器发回ID为1的电影。

Input:

输入:

{
  movie(id: 3) {
    name
    id
    year
  }
}

Output:

输出:

{
  "data": {
    "movie": {
      "name": "Movie 3",
      "id": "3",
      "year": 2016
    }
  }
}

In the above example name, id and year fields are requested. So the server sends back all of those fields.

在上面的示例名称中,要求提供id和year字段。 因此,服务器会发回所有这些字段。

导向器 (director)

Input:

输入:

{
  director(id: 1) {
    name
    id,
    age
  }
}

Output:

输出:

{
  "data": {
    "director": {
      "name": "Director 1",
      "id": "1",
      "age": 20
    }
  }
}

Input:

输入:

{
  director(id: 1) {
    name
    id,
    age,
    movies{
      name,
      year
    }
  }
}

Output:

输出:

{
  "data": {
    "director": {
      "name": "Director 1",
      "id": "1",
      "age": 20,
      "movies": [
        {
          "name": "Movie 1",
          "year": 2018
        },
        {
          "name": "Movie 2",
          "year": 2017
        }
      ]
    }
  }
}

In the above example, we see the power of GraphQL. We indicate we want a director with id 1. Also, we indicate we want all the movies by this director. Both the director and movie fields are customizable and the client can request exactly what it wants.

在上面的示例中,我们看到了GraphQL的强大功能。 我们表明我们想要一个ID为1的导演。此外,我们表明我们想要该导演的所有电影。 导演和电影字段都是可自定义的,客户可以确切地要求它想要什么。

Similarly, this can be extended to other fields and types. For example, we could run a query like Find a director with id 1. For this director find all the movies. For each of the movie find the actors. For each actor get the top 5 rated movies and so on. For this query, we need to specify the relationship between the types. Once we do that, the client can query any relationship it wants.

同样,它可以扩展到其他字段和类型。 例如,我们可以运行诸如查找ID为1的导演的查询。为此导演查找所有电影。 为每部电影找到演员。 对于每个演员,获得排名前5位的电影 ,依此类推。 对于此查询,我们需要指定类型之间的关系。 完成后,客户可以查询所需的任何关系。

恭喜😊 (Congrats 😊)

You now know the basic concepts of GraphQL.

您现在知道了GraphQL的基本概念。

You can check out the documentation to know more about GraphQL

您可以查看文档以了解有关GraphQL的更多信息

关于作者 (About the author)

I love technology and follow the advancements in the field. I also like helping others with my technology knowledge.

我热爱技术,并关注该领域的进步。 我也喜欢用我的技术知识来帮助他人。

Feel free to connect with me on my LinkedIn account https://www.linkedin.com/in/aditya1811/

随时使用我的LinkedIn帐户与我联系https://www.linkedin.com/in/aditya1811/

You can also follow me on twitter https://twitter.com/adityasridhar18

您也可以在Twitter上关注我https://twitter.com/adityasridhar18

My Website: https://adityasridhar.com/

我的网站: https : //adityasridhar.com/

Read more of my articles on my blog at adityasridhar.com.

adityasridhar.com的博客上阅读更多文章

翻译自: https://www.freecodecamp.org/news/an-introduction-to-graphql-how-it-works-and-how-to-use-it-91162ecd72d0/

graphql

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值