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
相关文章
|
13天前
|
存储 人工智能 NoSQL
使用 MongoDB 构建 AI:Gradient Accelerator Block 如何在几秒钟内让您从零开发 AI
借助 MongoDB,开发者可以存储任何结构的数据,然后使用单一查询 API 和驱动程序将这些数据用于 OLTP、文本搜索和向量搜索处理。
|
13天前
|
人工智能 NoSQL 测试技术
使用 MongoDB 构建 AI:Patronus 如何自动进行大语言模型评估来增强对生成式 AI 的信心
若需了解更多MongoDB Atlas相关内容,可前往:https://www.mongodb.com/zh-cn/atlas
使用 MongoDB 构建 AI:Patronus 如何自动进行大语言模型评估来增强对生成式 AI 的信心
|
6天前
|
NoSQL 前端开发 JavaScript
Node.js 连接 MongoDB
10月更文挑战第20天
15 0
|
13天前
|
人工智能 自然语言处理 NoSQL
|
13天前
|
存储 NoSQL MongoDB
小川科技携手阿里云数据库MongoDB:数据赋能企业构建年轻娱乐生态
基于MongoDB灵活模式的特性,小川实现了功能的快速迭代和上线,而数据库侧无需任何更改
|
17天前
|
NoSQL 前端开发 JavaScript
Node.js 连接 MongoDB
10月更文挑战第9天
34 0
|
24天前
|
JavaScript NoSQL 前端开发
使用 Node.js 和 MongoDB 构建实时聊天应用
【10月更文挑战第2天】使用 Node.js 和 MongoDB 构建实时聊天应用
|
3月前
|
JavaScript NoSQL 前端开发
|
27天前
|
存储 关系型数据库 MySQL
一个项目用5款数据库?MySQL、PostgreSQL、ClickHouse、MongoDB区别,适用场景
一个项目用5款数据库?MySQL、PostgreSQL、ClickHouse、MongoDB——特点、性能、扩展性、安全性、适用场景比较
|
4天前
|
NoSQL Cloud Native atlas
探索云原生数据库:MongoDB Atlas 的实践与思考
【10月更文挑战第21天】本文探讨了MongoDB Atlas的核心特性、实践应用及对云原生数据库未来的思考。MongoDB Atlas作为MongoDB的云原生版本,提供全球分布式、完全托管、弹性伸缩和安全合规等优势,支持快速部署、数据全球化、自动化运维和灵活定价。文章还讨论了云原生数据库的未来趋势,如架构灵活性、智能化运维和混合云支持,并分享了实施MongoDB Atlas的最佳实践。