Nodejs、GraphQL、MongoDB、Hapi 和 Swagger 构建 API(四)

本文涉及的产品
云数据库 MongoDB,独享型 2核8GB
推荐场景:
构建全方位客户视图
简介: 笔记

7.png可重用 API 流行的最大原因是 API 允许使用来自 Web 客户端、移动应用程序、桌面应用程序的数据,实际上是任何客户端。将构建一个基于 Nodejs,由 MongoDB 数据驱动的强大而灵活的 GraphQL API,并支持 Swagger 文档。

项目代码仓库:github.com/QuintionTan…

系列文章:


实施 GraphQL


8.png


GraphQL 究竟是什么?

GraphQL 的力量来自一个简单的想法,不是在服务器上定义响应的结构,而是将灵活性赋予了客户端。每个请求都指定了它想要返回的字段和关系,而 GraphQL 将构建一个为这个特定请求量身定制的响应。好处:只需要一次往返即可获取所有可能跨越多个 REST 端点的复杂数据,同时只返回实际需要的数据,仅此而已。

GraphQL 解决了传统 REST API 可能面临的一些痛点,如:

  • 过度获取:响应中有不使用的数据。
  • 取材不足:没有足够的数据来调用端点,导致需要调用第二个端点。

在这两种情况下,它们都可能带来性能问题:要么使用比理想情况更多的带宽,要么发出比理想情况更多的 HTTP 请求。

在一个完美的世界里,这些问题永远不会出现;将拥有完全正确的端点来为产品提供完全正确的数据。

当扩展和迭代产品时,经常会出现这些问题。在页面上使用的数据经常发生变化,并且为每个组件维护一个具有完全正确数据的单独端点的成本变得过高。

因此,最终会在没有太多端点和让端点最适合每个组件的需求之间做出折衷。这将导致在某些情况下过度获取(端点将提供比一个特定组件所需的数据更多的数据),并在其他一些情况下导致获取不足(将需要调用第二个端点)。

开始使用 GraphQL

首先,需要安装相应的依赖项。


yarn add graphql apollo-server-hapi

Graphql 是 graphql 的主要包,apollo-server-hapi 是 Hapi 服务器和 GraphQL 之间的粘合剂。

让项目根目录下创建一个名新的件夹 graphql,并在其目录下创建文件 PaintingType.js,代码如下:

const graphql = require("graphql");
const { GraphQLObjectType, GraphQLString } = graphql;
const PaintingType = new GraphQLObjectType({
    name: "Painting",
    fields: () => ({
        id: { type: GraphQLString },
        name: { type: GraphQLString },
        url: { type: GraphQLString },
        techniques: { type: GraphQLString },
    }),
});
module.exports = PaintingType;

代码创建了一个新的 GraphQLObjectType,定义的几乎所有 GraphQL 类型都是对象类型。对象类型有一个名称,但最重要的是描述它们的字段。GraphQL 是一种静态类型语言,这意味着必须为字段声明类型,代码中声明了所有字段类型都是 GraphQLString

现在需要为创建的 PaintingType 提供查询操作,在目录 graphql 创建文件 schema.js,代码如下:

const graphql = require("graphql");
const PaintingType = require("./PaintingType");
const { GraphQLObjectType, GraphQLString, GraphQLSchema } = graphql;
const Painting = require("./../models/Painting");
const RootQuery = new GraphQLObjectType({
    name: "RootQuery",
    fields: {
        painting: {
            type: PaintingType,
            args: { id: { type: GraphQLString } },
            resolve(parent, args) {
                // 保存数据逻辑
                return Painting.findById(args.id);
            },
        },
    },
});
module.exports = new GraphQLSchema({
    query: RootQuery,
});

上述代码将提供给服务器的根查询,字段部分现在更加复杂了,正在传递带有类型 PaintingTypeargs 字段的字段名称。那么如何找到一条 painting 特定的记录,需要某种参数来排序,在这种情况下,通常是 id

接下来,resolve 是带有两个参数的函数,parent 以及 args

只是为了说明,GraphQL 查询如下所示:

{
    painting(id:20){
        name
    }
}

painting 查询来自 PaintingType.js 如何传递一个参数,这是 resolve() 中的 args 参数,参数 parent 将用于更复杂的查询,在这些查询中有更多的嵌套。

接下来导出根查询并将其传递给 Hapi 服务器, GraphQLSchema 类型是传递给服务器的根查询/模式定义。

module.exports = new GraphQLSchema({
    query: RootQuery,
});

回到 server.js,增加 GraphQLschema.js 相关的逻辑。

const { graphiqlHapi, graphqlHapi } = require("apollo-server-hapi");
const schema = require("./graphql/schema");

接下来需要注册 hapi-graphql 插件,在 server.register({}) 中,传递了 GraphQL 配置。

await server.register({
    plugin: graphiqlHapi,
    options: {
        path: "/graphiql",
        graphiqlOptions: {
            endpointURL: "/graphql",
        },
        route: {
            cors: true,
        },
    },
});

安装了 graphiql 插件,注意它是 graphiql 而不是 graphql。接下来让注册一个新插件:graphqlHapi,它包含之前制作的模式。

await server.register({
    plugin: graphqlHapi,
    options: {
        path: "/graphql",
        graphqlOptions: {
            schema,
        },
        route: {
            cors: true,
        },
    },
});

现在,打开浏览器,输入 http://localhost:3006/graphiql

接下来在左侧输入查询语句:

{
  painting(id:"63a433eed0f861feafa369d4"){
    name,
    url
  }
}

9.png

执行之后结果如图:

10.png

至此,GraphQL 已经添加到项目中了,后续需要根据最新的版本优化代码。



相关实践学习
MongoDB数据库入门
MongoDB数据库入门实验。
快速掌握 MongoDB 数据库
本课程主要讲解MongoDB数据库的基本知识,包括MongoDB数据库的安装、配置、服务的启动、数据的CRUD操作函数使用、MongoDB索引的使用(唯一索引、地理索引、过期索引、全文索引等)、MapReduce操作实现、用户管理、Java对MongoDB的操作支持(基于2.x驱动与3.x驱动的完全讲解)。 通过学习此课程,读者将具备MongoDB数据库的开发能力,并且能够使用MongoDB进行项目开发。   相关的阿里云产品:云数据库 MongoDB版 云数据库MongoDB版支持ReplicaSet和Sharding两种部署架构,具备安全审计,时间点备份等多项企业能力。在互联网、物联网、游戏、金融等领域被广泛采用。 云数据库MongoDB版(ApsaraDB for MongoDB)完全兼容MongoDB协议,基于飞天分布式系统和高可靠存储引擎,提供多节点高可用架构、弹性扩容、容灾、备份回滚、性能优化等解决方案。 产品详情: https://www.aliyun.com/product/mongodb
相关文章
|
25天前
|
JSON 缓存 JavaScript
深入浅出:使用Node.js构建RESTful API
在这个数字时代,API已成为软件开发的基石之一。本文旨在引导初学者通过Node.js和Express框架快速搭建一个功能完备的RESTful API。我们将从零开始,逐步深入,不仅涉及代码编写,还包括设计原则、最佳实践及调试技巧。无论你是初探后端开发,还是希望扩展你的技术栈,这篇文章都将是你的理想指南。
|
18天前
|
JSON JavaScript 前端开发
深入浅出Node.js:从零开始构建RESTful API
在数字化时代的浪潮中,后端开发作为连接用户与数据的桥梁,扮演着至关重要的角色。本文将引导您步入Node.js的奇妙世界,通过实践操作,掌握如何使用这一强大的JavaScript运行时环境构建高效、可扩展的RESTful API。我们将一同探索Express框架的使用,学习如何设计API端点,处理数据请求,并实现身份验证机制,最终部署我们的成果到云服务器上。无论您是初学者还是有一定基础的开发者,这篇文章都将为您打开一扇通往后端开发深层知识的大门。
34 12
|
22天前
|
Java 测试技术 API
详解Swagger:Spring Boot中的API文档生成与测试工具
详解Swagger:Spring Boot中的API文档生成与测试工具
34 4
|
24天前
|
JavaScript NoSQL API
深入浅出Node.js:从零开始构建RESTful API
在数字化时代的浪潮中,后端开发如同一座灯塔,指引着数据的海洋。本文将带你航行在Node.js的海域,探索如何从一张白纸到完成一个功能完备的RESTful API。我们将一起学习如何搭建开发环境、设计API结构、处理数据请求与响应,以及实现数据库交互。准备好了吗?启航吧!
|
26天前
|
缓存 负载均衡 JavaScript
构建高效后端服务:Node.js与Express框架实践
在数字化时代的浪潮中,后端服务的重要性不言而喻。本文将通过深入浅出的方式介绍如何利用Node.js及其强大的Express框架来搭建一个高效的后端服务。我们将从零开始,逐步深入,不仅涉及基础的代码编写,更会探讨如何优化性能和处理高并发场景。无论你是后端新手还是希望提高现有技能的开发者,这篇文章都将为你提供宝贵的知识和启示。
|
28天前
|
JSON JavaScript 前端开发
使用JavaScript和Node.js构建简单的RESTful API
使用JavaScript和Node.js构建简单的RESTful API
|
2月前
|
存储 关系型数据库 MySQL
一个项目用5款数据库?MySQL、PostgreSQL、ClickHouse、MongoDB区别,适用场景
一个项目用5款数据库?MySQL、PostgreSQL、ClickHouse、MongoDB——特点、性能、扩展性、安全性、适用场景比较
|
8天前
|
存储 NoSQL 关系型数据库
阿里云数据库MongoDB版助力信也科技 打造互联网金融企业样板
我们的风控系统引入阿里云数据库MongoDB版后,解决了特征类字段灵活加减的问题,大大提高了开发效率,极大的提升了业务用户体验,获得了非常好的效果
阿里云数据库MongoDB版助力信也科技 打造互联网金融企业样板
|
1月前
|
NoSQL Cloud Native atlas
探索云原生数据库:MongoDB Atlas 的实践与思考
【10月更文挑战第21天】本文探讨了MongoDB Atlas的核心特性、实践应用及对云原生数据库未来的思考。MongoDB Atlas作为MongoDB的云原生版本,提供全球分布式、完全托管、弹性伸缩和安全合规等优势,支持快速部署、数据全球化、自动化运维和灵活定价。文章还讨论了云原生数据库的未来趋势,如架构灵活性、智能化运维和混合云支持,并分享了实施MongoDB Atlas的最佳实践。
|
2月前
|
NoSQL Cloud Native atlas
探索云原生数据库:MongoDB Atlas 的实践与思考
【10月更文挑战第20天】本文探讨了MongoDB Atlas的核心特性、实践应用及对未来云原生数据库的思考。MongoDB Atlas作为云原生数据库服务,具备全球分布、完全托管、弹性伸缩和安全合规等优势,支持快速部署、数据全球化、自动化运维和灵活定价。文章还讨论了实施MongoDB Atlas的最佳实践和职业心得,展望了云原生数据库的发展趋势。
下一篇
DataWorks