首页 >web前端 >js教程 >使用node.js和mongodb创建GraphQl Server

使用node.js和mongodb创建GraphQl Server

Christopher Nolan
Christopher Nolan原创
2025-02-18 10:37:13973浏览

使用node.js和mongodb创建GraphQl Server

钥匙要点

  • >使用node.js并Express来建立服务器并将MongoDB与Mongoose集成以进行数据管理,从而增强了服务器有效地处理查询和突变的能力。
  • >
  • >使用Express-GraphQL中间件在服务器上实现GraphQl,该中间件简化了HTTP请求的处理和JSON响应的输出,重点是创建用户友好的JSON格式。
  • 定义一个由类型,查询和突变组成的GraphQL模式,以精确管理数据交互,以确保数据结构与MongoDB模型一致性和安全性一致。
  • >>>>>
  • >通过利用GraphQl查询来在单个HTTP请求中获取特定数据字段来优化数据检索,从而大大降低了传输的数据量并改善了性能,尤其是在具有较慢的网络连接的移动设备上。
  • >使用Postman之类的工具来测试GraphQL端点,以验证查询和突变的设置和功能,以确保服务器对各种数据请求正确响应。
  • >
  • 本文是由Ryan Chenkie审查的。感谢SitePoint所有的同行评审员制作SitePoint内容的最佳状态!
>从客户端请求服务器的数据不是一个新概念。它允许应用程序加载数据而无需刷新页面。这是单页应用程序中最常使用的,该应用程序不是从服务器中获取渲染页面,而仅请求将其渲染在客户端端所需的数据。

> 在过去几年中,整个网络上最常见的方法是其余的建筑风格。但是,这种方法给高数据需求应用带来了一些局限性。在一个恢复的系统中,我们需要提出多个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架构

对于GraphQl,要了解我们需要定义架构的请求。 GraphQL模式不过是一组查询和突变。您可以将查询视为从数据库中检索和突变的资源,作为对数据库的任何更新。我们将创建一个示例博客文章和评论猫鼬模型,然后我们将为其创建一些查询和突变。

>

> mongoose模型

>让我们从创建猫鼬模型开始。在这里不会详细介绍,因为猫鼬不是本文的重点。您可以在型号/blog-post.js和Models/comment.js。

中找到两个模型

GraphQl types

喜欢猫鼬,在GraphQl中,我们需要定义数据结构。不同之处在于,我们为每个查询定义和突变,可以输入哪种类型的数据以及响应中发送的内容。如果这些类型不匹配,则会出现错误。尽管它看起来似乎是多余的,但由于我们已经定义了猫鼬的模式模型,但它具有很大的优势,例如:

>

您控制允许的内容,可以改善您的系统安全
  • >您控制允许的内容。这意味着您可以定义特定字段以永远不会被检索。例如:密码或其他敏感数据
  • >它过滤了无效的请求,因此不采取进一步的处理,可以改善服务器的性能
  • >您可以在GraphQl/types/中找到GraphQl类型的源代码。这是一个示例:
>

>在这里,我们正在定义博客输出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架构创建

>使用Mongoose模型和创建的GraphQL类型,我们现在可以创建我们的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

从查询开始,让我们从迄今为止创建的模型从一个示例中获取。一个很好的例子是获取博客文章及其所有评论。

> 在REST解决方案中,您必须为此提出两个HTTP请求。一个可以获取博客文章,另一个要获得评论,这看起来像这样:

在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/*的其他查询。我们不会经历每个示例,因为它们都与上面的示例相似。

>

突变

突变是可以在数据库中进行某种更改的操作。像查询一样,我们可以在单个HTTP请求中分组不同的突变。通常是孤立的,例如“添加评论”或“创建博客文章”。尽管随着应用程序和数据收集的复杂性不断增长,用于分析,用户体验测试或复杂操作,网站或应用程序上的用户操作可以触发大量突变,从而向数据库的不同资源触发。按照我们的示例,对我们的博客文章的新评论可能意味着新的评论,并对博客文章评论的更新进行了更新。在休息解决方案中,您将拥有类似以下内容:

<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端点

>现在我们已经使用GraphQL路由创建了Express Server,并进行了一些查询和突变,让我们通过向其发送一些请求来对其进行测试。

有很多方法可以将获取请求发送或将请求发布到一个位置,例如:>
  • 浏览器 - 通过在浏览器中键入一个URL,您会发送get请求。这有无法发送发布请求
  • 的限制
  • curl - 用于命令行风扇。它可以将任何类型的请求发送到服务器。虽然,这不是最好的界面,但您无法保存请求,并且需要在命令行中写所有内容,从我的角度来看,这不是理想的
  • GraphiQl - GraphQl的绝佳解决方案。这是一个浏览器IDE,您可以使用它来为服务器创建查询。它具有一些很棒的功能,例如:语法突出显示和键入
  • >
的解决方案比上述的解决方案更多。前两个是最著名和最使用的。 GraphIQL是GraphQL团队使用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>

使用node.js和mongodb创建GraphQl Server我们现在可以创建将具有JSON格式所需的GraphQl查询和变量的主体:

>

>假设您已经导入了我提供的集合,则应该已经有一些可以测试的查询和突变请求。由于我使用了硬编码的Mongo ID,因此按顺序运行请求,它们都应该成功。分析我在每个人的身体中放置的东西,您会发现这只是本文讨论的内容的应用。另外,如果您不止一次运行第一个请求,因为它将是重复的ID,您可以看到如何返回错误:

使用node.js和mongodb创建GraphQl Server

结论

在本文中,我们介绍了GraphQL的潜力以及它与REST体系结构样式的不同。这种新的查询语言将对网络产生重大影响。特别是对于更复杂的数据应用程序,现在可以准确地描述他们想要的数据,并使用单个HTTP请求请求。

我很想听听您的来信:您如何看待GraphQl,您对此的经历是什么?

使用node.js和mongodb

创建GraphQl Server的常见问题

>如何为我的GraphQl Server设置MongoDB数据库?

>为您的GraphQl Server设置MongoDB数据库涉及多个步骤。首先,您需要在本地计算机上安装MongoDB,或使用MongoDB Atlas等基于云的MongoDB服务。安装后,您可以创建一个新的数据库和集合。然后,您可以使用MongoDB client从node.js应用程序连接到此数据库。 Mongoose允许您为您的集合定义模式,并提供查询和操纵数据的方法。

>

>如何为我的mongoDB数据定义GraphQl架构?您的数据和可以对其执行的操作。在node.js应用程序中,您可以使用GraphQl库定义GraphQl架构。这涉及为您的数据,每种类型的字段定义类型以及可以在这些类型上执行的查询和突变。这些类型应匹配MongoDB集合中的文档的结构。

>

>如何处理GraphQl Server中的错误?

>

> >可以使用提供的formaterRor函数在GraphQl Server中完成错误处理。由阿波罗服务器。每当将错误丢弃在解析器中时,此功能就会称为。它接收错误作为参数,应返回错误对象。该对象可以包括一条消息,状态代码和任何其他相关信息。您也可以在解析器中使用试用器/捕获块来捕获和处理错误。

>

>如何优化我的GraphQl Server以进行性能?>有几种方法可以优化GraphQl Server进行性能。一种方法是将批处理和缓存与诸如DataLoader之类的库中。这可以减少对MongoDB数据库的请求数量并改善响应时间。另一种方法是使用持久的查询,该查询可以减少发送到服务器的请求的大小。您还可以使用监视工具(例如Apollo Studio)来识别和修复性能瓶颈。

>如何保护我的GraphQl Server?

确保GraphQl Server涉及多个步骤。首先,您应该使用HTTP来加密客户端和服务器之间的通信。您也可以使用头盔之类的库将安全标头添加到HTTP响应中。对于身份验证,您可以使用JSON Web令牌(JWT)并进行授权,可以使用GraphQl-Shield之类的库。您还应该验证和消毒用户输入以防止注射攻击。

如何测试我的GraphQl Server?

可以使用单元测试,集成测试,集成测试,测试GraphQl Server进行测试graphQl Server和端到端测试。您可以使用Jest之类的库来编写测试和Supertest之类的库来向您的服务器提出HTTP请求。您应该测试您的解析器,模式和mongoDB查询和突变。

>如何使用像Heroku这样的云服务来完成我的GraphQl Server?

​​

AWS或Google Cloud。您还应该设置连续集成和连续部署(CI/CD)管道以自动化部署过程。这可以使用诸如github操作或jenkins之类的服务来完成。

如何监视我的graphql server?

>监视GraphQl Server可以使用Apollo Studio或New Relic等服务来完成。这些服务提供了有关服务器性能的见解,包括响应时间,错误率和使用统计信息。当您的服务器存在问题时,它们还可以提醒您。

>如何使用GraphQl-upload(例如GraphQl-upload)来完成使用GraphQl?

​​

处理文件上传的文件上传。该库提供了一个可以在模式中使用的graphQlupload标量,并且可以在中间件中使用该库来处理上传的文件。>

以上是使用node.js和mongodb创建GraphQl Server的详细内容。更多信息请关注PHP中文网其他相关文章!

声明:
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn