> 在过去几年中,整个网络上最常见的方法是其余的建筑风格。但是,这种方法给高数据需求应用带来了一些局限性。在一个恢复的系统中,我们需要提出多个HTTP请求,以获取我们想要的所有数据,这具有重大的性能影响。如果有一种方法在单个HTTP请求中请求多个资源怎么办?> 介绍GraphQl,一种查询语言,可以统一客户端和服务器端之间的通信。它允许客户端在单个请求中准确地描述所需的数据。
> 在本文中,我们将使用GraphQl路由创建一个Node.js/Express Server,该路由将处理我们所有的查询和突变。然后,我们将通过发送一些帖子请求并使用Postman分析结果来测试此路线。>您可以在此处找到此应用程序的完整源代码。我还制作了一个邮递员,您可以在此处下载。
>>在Express Server上设置GraphQl端点
第一件事是使用Express Framework创建我们的Node.js服务器。我们还将将MongoDB与Mongoose一起用于数据持久性,而Babel使用ES6。由于该代码在运行时被转移到ES5,因此无需构建过程。这是在index.js中完成的:
<span>// index.js </span><span>require('babel/register'); </span><span>require('./app'); </span>
>在app.js中,我们将启动服务器,使用mongo数据库连接并创建GraphQl路由。
在本文上下文中,上面代码中最相对的部分是我们定义GraphQl路由的位置。我们使用Facebook GraphQL团队开发的Express中间件Express-GraphQL。这将通过GraphQL处理HTTP请求并返回JSON响应。为此,我们需要在下一节中讨论的GraphQL模式的选项中通过。我们还将选项设置为真实。这使JSON的响应非常印刷,使其更易于阅读。<span>// app.js </span><span>import express from 'express'; </span><span>import graphqlHTTP from 'express-graphql'; </span><span>import mongoose from 'mongoose'; </span> <span>import schema from './graphql'; </span> <span>var app = express(); </span> <span>// GraphqQL server route </span>app<span>.use('/graphql', graphqlHTTP(req => ({ </span> schema<span>, </span> <span>pretty: true </span><span>}))); </span> <span>// Connect mongo database </span>mongoose<span>.connect('mongodb://localhost/graphql'); </span> <span>// start server </span><span>var server = app.listen(8080, () => { </span> <span>console.log('Listening at port', server.address().port); </span><span>}); </span>>
graphQl架构
> mongoose模型
GraphQl types
您控制允许的内容,可以改善您的系统安全
>在这里,我们正在定义博客输出graphql类型,在创建查询和突变时,我们将进一步使用。请注意,结构与猫鼬模型Blogpost有多相似。这似乎可以重复工作,但这些是分开的关注点。 Mongoose模型定义了数据库的数据结构,GraphQL类型定义了服务器的查询或突变中所接受的规则。
<span>// graphql/types/blog-post.js </span><span>import <span>{ </span></span><span> <span>GraphQLObjectType, </span></span><span> <span>GraphQLNonNull, </span></span><span> <span>GraphQLString, </span></span><span> <span>GraphQLID </span></span><span><span>}</span> from 'graphql'; </span> <span>export default new GraphQLObjectType({ </span> <span>name: 'BlogPost', </span> <span>fields: { </span> <span>_id: { </span> <span>type: new GraphQLNonNull(GraphQLID) </span> <span>}, </span> <span>title: { </span> <span>type: GraphQLString </span> <span>}, </span> <span>description: { </span> <span>type: GraphQLString </span> <span>} </span> <span>} </span><span>}); </span>>
graphQl架构创建
在这里,我们导出一个graphqlschema,在其中定义了两个属性:查询和突变。 GraphQlobjectType是众多GraphQL类型之一。特别是,您可以指定:
>我们传递到字段的查询和突变变量是普通的JavaScript对象。键是突变或查询名称。这些值是带有配置的普通JavaScript对象,该对象告诉GraphQl如何处理它们。让我们以以下GraphQl查询为例:
>>要使GrahPQL了解该查询的方法,我们需要定义Blogposts和评论查询。因此,我们的查询变量将是这样的:
<span>// index.js </span><span>require('babel/register'); </span><span>require('./app'); </span>>
突变也是如此。这是为了解释我们在查询或突变中所拥有的键与我们在查询中的名称之间存在直接关系。现在让我们看看这些查询和突变中的每一个。
><span>// app.js </span><span>import express from 'express'; </span><span>import graphqlHTTP from 'express-graphql'; </span><span>import mongoose from 'mongoose'; </span> <span>import schema from './graphql'; </span> <span>var app = express(); </span> <span>// GraphqQL server route </span>app<span>.use('/graphql', graphqlHTTP(req => ({ </span> schema<span>, </span> <span>pretty: true </span><span>}))); </span> <span>// Connect mongo database </span>mongoose<span>.connect('mongodb://localhost/graphql'); </span> <span>// start server </span><span>var server = app.listen(8080, () => { </span> <span>console.log('Listening at port', server.address().port); </span><span>}); </span>QUERIES
从查询开始,让我们从迄今为止创建的模型从一个示例中获取。一个很好的例子是获取博客文章及其所有评论。
在GraphQl中,我们只能在一个http请求中进行以下查询:
>我们可以在一个请求中获取我们想要的所有数据,这单独提高了性能。我们还可以要求我们要使用的确切属性。在上面的示例中,响应只会带来博客文章的标题和描述,评论只会带来文字。
。<span>// graphql/types/blog-post.js </span><span>import <span>{ </span></span><span> <span>GraphQLObjectType, </span></span><span> <span>GraphQLNonNull, </span></span><span> <span>GraphQLString, </span></span><span> <span>GraphQLID </span></span><span><span>}</span> from 'graphql'; </span> <span>export default new GraphQLObjectType({ </span> <span>name: 'BlogPost', </span> <span>fields: { </span> <span>_id: { </span> <span>type: new GraphQLNonNull(GraphQLID) </span> <span>}, </span> <span>title: { </span> <span>type: GraphQLString </span> <span>}, </span> <span>description: { </span> <span>type: GraphQLString </span> <span>} </span> <span>} </span><span>}); </span>>仅从每个资源中检索所需的字段,可以对网页或应用程序的加载时间产生巨大影响。让我们看一下评论,这些评论也具有_id和postid属性。这些中的每一个都是小的,每个都确切的12个字节(不使用对象键计数)。当它是单个或几个评论时,这几乎没有影响。当我们谈论的是200条评论时,我们甚至都不会使用的4800个字节。这可以对应用程序加载时间产生重大影响。这对于资源有限的设备(例如移动设备)通常具有较慢的网络连接。
为此,我们需要告诉GraphQl如何为每个特定查询获取数据。让我们看看查询定义的示例:
<span>// index.js </span><span>require('babel/register'); </span><span>require('./app'); </span>
>在这里,我们正在创建一个根据ID参数检索单个博客文章的查询。请注意,我们正在指定以前创建的类型,该类型验证了查询的输出。我们还设置了一个ARGS对象,并具有此查询所需的参数。最后,我们查询数据库并返回数据的解决方案函数。
> 为了进一步优化获取数据的过程并利用了MongoDB上的投影功能,我们正在处理GraphQL为我们提供与Mongoose兼容的投影的AST。因此,如果我们进行以下查询:
<span>// app.js </span><span>import express from 'express'; </span><span>import graphqlHTTP from 'express-graphql'; </span><span>import mongoose from 'mongoose'; </span> <span>import schema from './graphql'; </span> <span>var app = express(); </span> <span>// GraphqQL server route </span>app<span>.use('/graphql', graphqlHTTP(req => ({ </span> schema<span>, </span> <span>pretty: true </span><span>}))); </span> <span>// Connect mongo database </span>mongoose<span>.connect('mongodb://localhost/graphql'); </span> <span>// start server </span><span>var server = app.listen(8080, () => { </span> <span>console.log('Listening at port', server.address().port); </span><span>}); </span>>由于我们只需要从数据库中获取标题和描述,因此getProcotion函数将生成一个有效的投影:
<span>// graphql/types/blog-post.js </span><span>import <span>{ </span></span><span> <span>GraphQLObjectType, </span></span><span> <span>GraphQLNonNull, </span></span><span> <span>GraphQLString, </span></span><span> <span>GraphQLID </span></span><span><span>}</span> from 'graphql'; </span> <span>export default new GraphQLObjectType({ </span> <span>name: 'BlogPost', </span> <span>fields: { </span> <span>_id: { </span> <span>type: new GraphQLNonNull(GraphQLID) </span> <span>}, </span> <span>title: { </span> <span>type: GraphQLString </span> <span>}, </span> <span>description: { </span> <span>type: GraphQLString </span> <span>} </span> <span>} </span><span>}); </span>>您可以在源代码中查看graphql/queries/*的其他查询。我们不会经历每个示例,因为它们都与上面的示例相似。
>
突变
<span>// graphql/index.js </span><span>import <span>{ </span></span><span> <span>GraphQLObjectType, </span></span><span> <span>GraphQLSchema </span></span><span><span>}</span> from 'graphql'; </span> <span>import mutations from './mutations'; </span><span>import queries from './queries'; </span> <span>export default new GraphQLSchema({ </span> <span>query: new GraphQLObjectType({ </span> <span>name: 'Query', </span> <span>fields: queries </span> <span>}), </span> <span>mutation: new GraphQLObjectType({ </span> <span>name: 'Mutation', </span> <span>fields: mutations </span> <span>}) </span><span>}); </span>>使用GraphQl,您只能在一个http请求中使用以下内容进行操作:
>
query <span>{ </span> blogPosts <span>{ </span> _id<span>, </span> title <span>} </span> comments <span>{ </span> text <span>} </span><span>} </span>请注意,查询和突变的语法完全相同,只是将查询更改为突变。 我们可以从突变中询问数据,就像我们从查询中相同的方式。通过不指定片段,就像我们在上面的BlogPostCommentin中的查询中一样,我们只是在问一个真或错误的返回值,这通常足以确认操作。或者我们可以要求提供一些数据,例如对附加组件突变,这对于仅检索服务器上生成的数据很有用。
> 然后,让我们在服务器中定义我们的突变。突变是完全作为查询创建的:
这个突变将添加新的博客文章,并在成功(如果成功)返回true。请注意,在类型中,我们指定将要返回的内容。在Args中,从突变中收到的论点。 and lesolve()函数与查询定义完全一样。
<span>{ </span> <span>blogPosts: {...}, </span> <span>comments: {...} </span><span>} </span>>
测试GraphQl端点
在这三个中,我建议GraphiQl,尽管我更喜欢并最重要的是邮递员。该工具绝对是API测试的预付款。它提供了一个直观的接口,您可以在其中创建并保存任何类型的请求的集合。您甚至可以为您的API创建测试,并单击按钮。它还具有协作功能,并使其能够共享请求的集合。因此,我创建了一个可以在此处下载的,然后您可以将其导入到Postman。如果您没有安装邮递员,我绝对建议您这样做。
>>让我们从运行服务器开始。您应该安装4个或更高的节点;如果您还没有,我建议使用NVM安装它。然后,我们可以在命令行中运行以下内容:
>服务器现在可以接收请求,因此让我们在Postman上创建一些。我们的GraphQL路由设置为/GraphQl,因此首先要做的就是将位置设置为我们要指导我们的请求的位置,即http:// localhost:8080/graphql。然后,我们需要指定它是GET还是邮政请求。尽管您可以使用其中的任何一个,但我更喜欢发布,因为它不会影响URL,从而使其更清洁。我们还需要配置随请求随附的标头,在我们的情况下,我们只需要添加与应用程序/JSON等于的内容类型。这是Postman中的所有外观:
<span>// index.js </span><span>require('babel/register'); </span><span>require('./app'); </span>
我们现在可以创建将具有JSON格式所需的GraphQl查询和变量的主体:
>假设您已经导入了我提供的集合,则应该已经有一些可以测试的查询和突变请求。由于我使用了硬编码的Mongo ID,因此按顺序运行请求,它们都应该成功。分析我在每个人的身体中放置的东西,您会发现这只是本文讨论的内容的应用。另外,如果您不止一次运行第一个请求,因为它将是重复的ID,您可以看到如何返回错误:
我很想听听您的来信:您如何看待GraphQl,您对此的经历是什么?
使用node.js和mongodb
创建GraphQl Server的常见问题>如何为我的mongoDB数据定义GraphQl架构?您的数据和可以对其执行的操作。在node.js应用程序中,您可以使用GraphQl库定义GraphQl架构。这涉及为您的数据,每种类型的字段定义类型以及可以在这些类型上执行的查询和突变。这些类型应匹配MongoDB集合中的文档的结构。
>> >可以使用提供的formaterRor函数在GraphQl Server中完成错误处理。由阿波罗服务器。每当将错误丢弃在解析器中时,此功能就会称为。它接收错误作为参数,应返回错误对象。该对象可以包括一条消息,状态代码和任何其他相关信息。您也可以在解析器中使用试用器/捕获块来捕获和处理错误。
>处理文件上传的文件上传。该库提供了一个可以在模式中使用的graphQlupload标量,并且可以在中间件中使用该库来处理上传的文件。
以上是使用node.js和mongodb创建GraphQl Server的详细内容。更多信息请关注PHP中文网其他相关文章!