Mutations
大多数关于 GraphQL 的讨论都侧重于数据获取,但任何完整的数据平台都需要一种修改服务器端数据的方式。 在 REST 中,任何请求都可能导致对服务器的副作用,但最佳实践建议我们不应该在 GET 请求中修改数据。 GraphQL 类似 - 从技术上讲,任何查询都可以被实现为导致数据写入。 然而,与 REST 一样,建议遵循约定,即任何导致写入的操作都应该通过显式发送变更来完成(在此处阅读更多)。
官方的 Apollo
文档使用了一个 upvotePost() 变更的例子。该变更实现了一个增加帖子投票属性值的方法。
为了在 Nest 中创建一个等效的变更,我们将利用 @Mutation()
装饰器。
代码优先
让我们在上一节中使用的 AuthorResolver 中添加另一个方法(请参阅解析器)。
@Mutation(returns => Post)
async upvotePost(@Args({ name: 'postId', type: () => Int }) postId: number) {
return this.postsService.upvoteById({ id: postId });
}
所有装饰器(例如 @Resolver
、@ResolveField
、@Args
等)都是从 @nestjs/graphql
包中导出的。
这将导致在 GraphQL 架构中生成以下部分:
type Mutation {
upvotePost(postId: Int!): Post
}
upvotePost()
方法将 postId(Int
)作为参数,并返回更新后的 Post
实体。
出于解析器部分解释的原因,我们必须显式设置预期的类型。
如果变更需要将对象作为参数传递,我们可以创建一个输入类型。
输入类型是一种特殊的对象类型,
可以作为参数传递(在此处阅读更多)。
要声明输入类型,请使用 @InputType()
装饰器。
import { InputType, Field } from '@nestjs/graphql';
@InputType()
export class UpvotePostInput {
@Field()
postId: number;
}
@InputType()
装饰器接受一个选项对象作为参数,因此您可以例如指定输入类型的描述。
请注意,由于 TypeScript 的元数据反射系统的限制,您必须使用 @Field
装饰器手动指定类型,
或者使用一个 CLI 插件。
然后我们可以在解析器类中使用此类型:
@Mutation(returns => Post)
async upvotePost(
@Args('upvotePostData') upvotePostData: UpvotePostInput,
) {}
模式优先
让我们扩展上一节中使用的 AuthorResolver
(请参阅解析器)。
@Mutation()
async upvotePost(@Args('postId') postId: number) {
return this.postsService.upvoteById({ id: postId });
}
请注意,上面我们假设业务逻辑已经移到了 PostsService