变更操作
变更操作
在GraphQL中,变更用于修改服务器端数据(即读取、写入和删除数据)。变更的结构和语法与查询相同,但它们必须以mutation关键字开头。Apollo文档提供了关于变更的优秀概述。
代码优先
让我们添加另一个方法到我们的AuthorResolver中,用于创建新的作者(createAuthor)。
@Mutation(returns => Author)
async createAuthor(@Args('createAuthorInput') createAuthorInput: CreateAuthorInput) {
return this.authorsService.create(createAuthorInput);
}
提示 所有装饰器(例如,@Resolver、@ResolveField、@Args等)都从@nestjs/graphql包中导出。
上面的代码将在SDL中生成以下GraphQL模式的部分:
type Mutation {
createAuthor(createAuthorInput: CreateAuthorInput!): Author!
}
createAuthor()方法接受一个CreateAuthorInput对象作为参数。CreateAuthorInput是一个输入类型。输入类型与对象类型的不同之处在于它们的用途。输入类型用作参数,而对象类型可以作为返回类型返回。要定义输入类型,请使用@InputType()装饰器。
import { InputType, Field } from '@nestjs/graphql';
@InputType()
export class CreateAuthorInput {
@Field()
firstName: string;
@Field()
lastName: string;
}
提示 同样,由于TypeScript的元数据反射系统的限制,您必须使用@Field()装饰器手动指示类型和可选性,或使用CLI插件。
与@ObjectType()一样,@Field()装饰器接受可选的类型函数和选项对象,包括以下属性:
nullable:用于指定字段是否可空description:用于设置字段描述deprecationReason:用于将字段标记为已弃用defaultValue:用于设置默认值
例如:
@Field({ description: `作者的名字`, deprecationReason: '在v2模式中不再有用' })
firstName: string;
上面的代码将在SDL中生成以下部分:
input CreateAuthorInput {
firstName: String! @deprecated(reason: "在v2模式中不再有用")
lastName: String!
}
模式优先
让我们扩展我们在前一节中使用的模式。
type Author {
id: Int!
firstName: String
lastName: String
posts: [Post]
}
type Post {
id: Int!
title: String!
votes: Int
}
type Query {
author(id: Int!): Author
}
type Mutation {
createAuthor(createAuthorInput: CreateAuthorInput!): Author!
}
input CreateAuthorInput {
firstName: String!
lastName: String!
}
现在让我们创建一个解析器方法来处理变更。
@Mutation('createAuthor')
async create(@Args('createAuthorInput') createAuthorInput: CreateAuthorInput) {
return this.authorsService.create(createAuthorInput);
}
上面的create()方法将接受一个CreateAuthorInput对象作为参数。
类型定义
如果我们使用模式优先方法,我们还需要创建相应的TypeScript定义。
export class CreateAuthorInput {
firstName: string;
lastName: string;
}
我们可以通过启用自动生成TypeScript定义来减少冗余工作(如前一章所示)。自动生成的类型如下所示:
export class CreateAuthorInput {
firstName: string;
lastName: string;
}
验证
无论您使用代码优先还是模式优先方法,您都可以利用验证装饰器。对于代码优先方法,在输入类型类上使用验证装饰器:
import { IsEmail, IsNotEmpty, IsOptional } from 'class-validator';
import { InputType, Field } from '@nestjs/graphql';
@InputType()
export class CreateAuthorInput {
@Field()
@IsNotEmpty()
@IsEmail()
email: string;
@Field({ nullable: true })
@IsOptional()
firstName?: string;
@Field({ nullable: true })
@IsOptional()
lastName?: string;
}
对于模式优先方法,您需要扩展自动生成的类:
import { IsEmail, IsNotEmpty, IsOptional } from 'class-validator';
import { CreateAuthorInput } from '../../graphql.ts';
export class CreateAuthorInputDto extends CreateAuthorInput {
@IsNotEmpty()
@IsEmail()
email: string;
@IsOptional()
firstName?: string;
@IsOptional()
lastName?: string;
}
然后在解析器中使用DTO而不是自动生成的CreateAuthorInput类:
@Mutation('createAuthor')
async create(@Args('createAuthorInput') createAuthorInput: CreateAuthorInputDto) {
return this.authorsService.create(createAuthorInput);
}