概述
GraphQL 是一种用于 API 的查询语言和运行时环境。它被设计为一种替代 REST API 的解决方案,提供了更高效、强大、灵活的数据查询和操纵方式。具有如下特点:
- 声明性数据获取: GraphQL 允许客户端明确声明需要从服务器获取哪些数据,以及需要获取的数据的结构。这种声明性的数据获取方式可以减少不必要的数据传输,提高效率。
- 单一端点: 与 REST 不同,GraphQL 通常只使用一个端点来处理所有的请求。客户端可以根据自己的需求精确地指定所需的数据,避免了在 REST 中可能出现的过度获取或获取不足的问题。
- 精确返回: GraphQL 返回的结果与客户端的请求一一对应,不多也不少。这样客户端就可以获得其需要的精确数据,而无需多次请求不同的端点或者在本地进行多次数据处理。
- 自动文档生成: 由于 GraphQL 查询语言的自描述性,可以轻松地生成文档。开发人员可以查看完整的 API 文档,包括可用查询、变更和类型等信息。
- 多平台兼容: GraphQL 不限定于特定的后端语言或前端框架,可以与各种技术栈和平台一起使用。
- 批量查询: GraphQL 支持一次发送多个请求,并在一个请求中获取多个资源,从而减少网络请求的数量。
创建API的通用步骤
1.安装相关依赖
安装四个依赖包
perl
"graphql": "^16.6.0",
"apollo-server-express": "^3.10.3",
"@nestjs/apollo": "^10.1.3",
"@nestjs/graphql": "^10.1.3"
graphql (^16.6.0):
作用: 这是 GraphQL 的 JavaScript/TypeScript 实现。它包含了用于定义和执行 GraphQL 操作的核心库。你可以使用它在 Node.js 服务器上构建 GraphQL 服务,或者在客户端发起 GraphQL 查询。
apollo-server-express (^3.10.3):
作用: 这是 Apollo Server 的 Express 版本。Apollo Server 是一个用于构建 GraphQL 服务的开源工具。apollo-server-express 可以与 Express 框架集成,提供了在 Express 应用中轻松创建 GraphQL 服务的能力。它还支持 GraphQL 的特性,如实时查询(subscriptions)等。
@nestjs/apollo (^10.1.3):
作用: 这是 NestJS 的官方 GraphQL 模块。NestJS 是一个基于 TypeScript 的服务器端框架,@nestjs/apollo 模块扩展了 NestJS,使其能够更容易地与 Apollo Server 集成。它提供了一些用于定义 GraphQL 模块、服务和控制器的装饰器,简化了 GraphQL 在 NestJS 应用中的使用。
@nestjs/graphql (^10.1.3):
作用: 这也是 NestJS 的官方 GraphQL 模块。与 @nestjs/apollo 不同,@nestjs/graphql 提供了一种不依赖于 Apollo Server 的纯粹 NestJS 的 GraphQL 模块。它允许你使用 NestJS 的方式来定义 GraphQL 模块、服务和控制器,而不依赖于特定的 GraphQL 服务器实现。
这四个包通常一起使用,用于在 NestJS 应用中构建和处理 GraphQL 服务。可以选择使用 Apollo Server 或者纯粹的 NestJS GraphQL 模块,这取决于你的项目需求和喜好。graphql 是核心的 GraphQL 实现,而 apollo-server-express、@nestjs/apollo、@nestjs/graphql 是用于在 Node.js 应用中构建 GraphQL 服务的框架和库。
2.注册GraphQLModule
在app.module.ts
中注册GraphQLModule 。
php
GraphQLModule.forRoot({
driver: ApolloDriver,
autoSchemaFile: true,
}),
在Nest.js中使用GraphQLModule.forRoot
方法来配置和启用GraphQL服务时,你可以传递一个包含配置选项的对象。在你提供的代码片段中,GraphQLModule.forRoot的配置选项如下:
driver: ApolloDriver:
这个选项指定了使用的GraphQL驱动程序。在这个配置中,ApolloDriver表示使用Apollo Server作为GraphQL服务的驱动程序。Apollo Server是一个流行的GraphQL服务器实现,它提供了许多功能,例如性能追踪、错误处理、数据缓存等。用于构建和处理GraphQL API,通过选择适当的驱动程序,你可以根据你的需求使用不同的GraphQL实现。
autoSchemaFile: true: 这个选项用于自动生成GraphQL模式文件。GraphQL模式文件(通常是.graphql或.gql文件)定义了可用的GraphQL查询、类型和操作。当设置为true时,Nest.js会在应用程序启动时根据你的Resolver和Type定义自动生成这个模式文件。这个模式文件在开发过程中非常有用,因为它可以用于文档生成、客户端代码生成等目的。
总之,通过这个配置,你告诉Nest.js使用Apollo Server作为GraphQL的驱动程序,并且启用了自动生成GraphQL模式文件的功能。这样,你就可以在应用程序中方便地定义和处理GraphQL查询,并且可以使用自动生成的模式文件进行相关的开发和文档工作。
3.创建Resolver
在GraphQL中,Resolver(解析器)是用来定义GraphQL查询的执行逻辑的函数。每个字段在GraphQL查询中都可以有一个相应的解析器。当客户端发起一个GraphQL查询时,服务器端的解析器就会被调用,用来处理查询并返回相应的数据。
定义输入输出类型
kotlin
import { Field, InputType } from '@nestjs/graphql';
@InputType()
export class UserInput {
@Field()
name: string;
@Field()
desc: string;
}
上述代码中:
@InputType() 装饰器:@InputType() 是一个装饰器,用于将一个普通的 TypeScript 类标记为 GraphQL 的输入类型。输入类型通常用于表示客户端向服务器发送的数据的结构,例如用于创建或更新某个资源的请求数据。
@Field() 装饰器:@Field() 也是一个装饰器,它用于将一个类的属性标记为 GraphQL 的字段。在输入类型中,@Field() 装饰器用于定义客户端可以传递的字段。
定义 UserInput 类中的属性 name 和 desc 为 GraphQL 的字段。这意味着在 GraphQL 查询中,客户端可以使用 name 和 desc 作为字段名,传递相应的值。在这个例子中,name 和 desc 都被定义为字符串类型的字段。
定义输出类型:
kotlin
import { Field, ObjectType } from '@nestjs/graphql';
@ObjectType()
export class UserType {
@Field()
id?: string;
@Field()
name?: string;
@Field()
desc: string;
@Field()
account: string;
}
@ObjectType() 装饰器将 UserType 类标记为 GraphQL 的对象类型。这意味着它可以被用作 GraphQL 查询的返回类型。
@Field() 装饰器用于定义 UserType 类中的属性 id、name、desc 和 account 为 GraphQL 的字段。这意味着在 GraphQL 查询中,客户端可以请求这些字段的值。在这个例子中,id 和 name 字段被定义为可选的字符串类型,而 desc 和 account 字段被定义为必需的字符串类型。
接下来编写具体的resolver代码
typescript
import { Args, Mutation, Query, Resolver } from '@nestjs/graphql';
import { UserService } from './user.service';
import { UserInput } from './dto/user-input.type';
import { UserType } from './dto/user.type';
@Resolver()
export class UserResolver {
constructor(private readonly userService: UserService) {}
@Mutation(() => Boolean, { description: '新增用户' })
async create(@Args('params') params: UserInput): Promise<boolean> {
return await this.userService.create(params);
}
@Query(() => UserType, { description: '使用 ID 查询用户' })
async find(@Args('id') id: string): Promise<UserType> {
return await this.userService.find(id);
}
}
下列代码中:
@Resolver()
: 是一个装饰器,它将类标记为一个GraphQL Resolver。Resolver是用于处理GraphQL查询和操作的类,其中定义了相应的查询字段和变更操作。
export class UserResolver { }:
这是一个GraphQL Resolver的类定义。该类负责处理与用户相关的GraphQL查询和变更请求。
constructor(private readonly userService: UserService) { }:
在UserResolver类的构造函数中,注入了一个UserService的实例。 这是依赖注入(Dependency Injection)的一种方式,它允许你在Resolver中使用UserService的方法,处理具体的业务逻辑。
@Mutation(() => Boolean, { description: '新增用户' }):
这是一个Mutation字段的定义。Mutation字段用于处理对数据进行变更的请求,这里定义了一个名为create的Mutation字段。它接受一个参数params,类型为UserInput,表示创建用户时需要提供的输入数据。返回类型为Boolean,表示操作成功或失败。{ description: '新增用户' }是对这个Mutation字段的描述。
async create(@Args('params') params: UserInput): Promise<boolean> { }:
这是create Mutation字段的具体处理函数。它使用@Args装饰器来获取传入的参数params,类型为UserInput,并调用UserService的create方法来创建用户。函数返回一个Promise,表示操作是否成功。
@Query(() => UserType, { description: '使用 ID 查询用户' }):
这是一个Query字段的定义。Query字段用于处理对数据的查询请求,这里定义了一个名为find的Query字段。它接受一个参数id,表示要查询的用户ID。返回类型为UserType,表示查询结果的数据类型。{ description: '使用 ID 查询用户' }是对这个Query字段的描述。
async find(@Args('id') id: string): Promise { }: 这是find Query字段的具体处理函数。它使用@Args装饰器来获取传入的参数id,类型为string,并调用UserService的find方法来根据用户ID查询用户信息。函数返回一个Promise,表示查询结果。
总的来说,这段代码定义了一个GraphQL Resolver,包含了两个字段:一个Mutation字段用于创建用户,一个Query字段用于根据用户ID查询用户信息。Resolver中的具体操作通过依赖注入的方式,使用UserService中的方法来处理业务逻辑。
创建好resolver以后一定记得注册下
在 user.module.ts 里的 providers 里需要引入下 user.resolver.ts
python
import { Module, ConsoleLogger } from '@nestjs/common';
import { TypeOrmModule } from '@nestjs/typeorm';
import { UserService } from './user.service';
import { User } from './models/user.entity';
import { UserResolver } from './user.resolver';
@Module({
imports: [TypeOrmModule.forFeature([User])],
providers: [ConsoleLogger, UserService, UserResolver],
exports: [UserService],
})
export class UserModule {}
在Nest.js中,Resolver是用来处理GraphQL请求的函数,它包含了处理请求的逻辑。当你创建了一个新的Resolver后,你需要将它注册到Nest.js应用程序的模块中,以便系统知道在收到相应的GraphQL请求时应该使用哪个Resolver来处理。
假设你在user.resolver.ts文件中创建了一个UserResolver,它包含了处理用户相关操作的逻辑,例如查询用户信息、创建用户等。在Nest.js中,你需要将这个UserResolver类添加到你的user.module.ts文件中的providers数组里,以便将它注册到Nest.js的依赖注入系统中。当GraphQL请求到达时,Nest.js会使用这个注册的UserResolver来处理请求。
ini
providers: [ConsoleLogger, UserService, UserResolver],
UserResolver被添加到UserModule模块的providers数组中。这样一来,当GraphQL请求中包含与UserResolver相关的查询时,Nest.js就会使用UserResolver中定义的逻辑来处理这些查询请求。
通过这种方式,确保了在GraphQL请求中使用UserResolver时,Nest.js知道应该使用哪个Resolver来处理请求,并且系统会按照你在UserResolver中定义的逻辑来执行相应的操作。
4.工具调试
随后通过graphql访问,就会进入一个可视化界面
用户修改
执行用户修改,这段代码是一个 GraphQL Mutation 操作的定义,用于在服务器端执行更新操作
php
mutation update($id: String!,$params: UserInput!){
update(id: $id, params: $params)
}
mutation update($id: String!, $params: UserInput!)
: 这行代码定义了一个 Mutation 操作,命名为 update。mutation 关键字表示这是一个用于更新或修改数据的 GraphQL 操作。
$id: String!
: 这是一个输入参数,表示要更新的对象的唯一标识符。String! 表示这是一个非空的字符串类型。
$params: UserInput!
: 这是另一个输入参数,表示要更新的对象的新属性。UserInput! 表示这是一个非空的自定义输入类型(通常是一个包含多个字段的对象)。
update(id: $id, params: $params)
: 这是 Mutation 操作的主体,调用了名为 update 的实际处理函数(或者后端的 resolver 函数)。在这里,id 和 params 是从 Mutation 操作的输入参数中传递进来的。
$id 和 $params
: 这是通过 Mutation 操作的参数传递给后端的实际值。 <math xmlns="http://www.w3.org/1998/Math/MathML"> i d 对应了前面定义的 id 对应了前面定义的 </math>id对应了前面定义的id 输入参数, <math xmlns="http://www.w3.org/1998/Math/MathML"> p a r a m s 对应了 params 对应了 </math>params对应了params 输入参数。
在实际使用时,你需要提供一个对应于这个 Mutation 操作的 resolver 函数,这个函数会接收到传递进来的 id 和 params 参数,并执行相应的数据更新逻辑。这种结构的 GraphQL Mutation 操作允许客户端以一种清晰和结构化的方式指定数据更新的要求。
请求参数
json
{
"id": "22820297-e288-42ba-aadf-3a4062c5c3cb",
"params": {
"desc": "超级管理员",
"name": "麦子0"
}
}
执行完成之后,可以看到数据确实发生变化
删除用户
现在将数据库服务器中这一条数据删除,
这段代码是一个 GraphQL Resolver 中的 Mutation 操作的定义,用于删除用户
less
@Mutation(() => Boolean, { description: '删除用户' })
async del(@Args('id') id: string): Promise<boolean> {
return await this.userService.del(id);
}
@Mutation(() => Boolean, { description: '删除用户' })
: 这是一个装饰器,用于定义 Mutation 操作。@Mutation 表示这是一个 Mutation 操作,() => Boolean 表示该 Mutation 的返回类型为布尔值,即表示操作的成功或失败。{ description: '删除用户' } 是对这个 Mutation 操作的描述。
async del(@Args('id') id: string): Promise<boolean>
: 这是 Mutation 操作的实际方法,被命名为 del。它是一个异步方法,接受一个参数 id,表示要删除的用户的唯一标识符,返回一个 Promise,表示删除操作的结果。
@Args('id') id: string
: 这是一个装饰器,表示从客户端传递进来的参数。在这里,id 是通过 Mutation 操作传递给 resolver 的参数,它表示要删除的用户的唯一标识符。
return await this.userService.del(id);
: 在方法内部,通过调用 this.userService.del 方法,使用了注入的 UserService 来执行删除用户的操作。传递给 del 方法的参数是用户的唯一标识符 id。
返回值: 删除操作的结果会被封装在一个布尔类型的 Promise 中,表示删除是否成功。在这个例子中,true 可能表示删除成功,false 可能表示删除失败。
这样,当客户端发起删除用户的 Mutation 请求时,会调用 del 方法执行删除操作,并返回删除操作的结果。
在graphql中进行测试
python
mutation del($id: String!){
del(id: $id)
}
json
{
"id": "8dcc8724-3cab-404b-bc61-7e7775774ea5"
}