Mutation

GraphQLのほとんどの議論はデータの取得に焦点を当てていますが、完全なデータプラットフォームには、サーバー側のデータを変更する方法も必要です。RESTでは、どのようなリクエストもサーバー上で副作用を引き起こす可能性がありますが、ベストプラクティスではGETリクエストでデータを変更すべきではないとしています。GraphQLも同様で、技術的にはどのようなクエリでもデータの書き込みを引き起こすように実装することが可能です。しかし、RESTと同様に、書き込みを引き起こす操作は変異を通じて明示的に送信されるべきであるという慣習を守ることが推奨されます(詳しくはこちらをご覧ください)。
Apolloの公式ドキュメントでは、upvotePost()変異の例を使用しています。この変異は、投稿の投票数プロパティの値を増加させるメソッドを実装しています。Nestで同等の変異を行うには、@Mutation()デコレータを使用します。

コードファースト

以前のセクションで使用したAuthorResolverに別のメソッドを追加してみましょう(【Resolver(コードファースト)】を参照)。
@Mutation(returns => Post)
async upvotePost(@Args({ name: 'postId', type: () => Int }) postId: number) {
return this.postsService.upvoteById({ id: postId });
}
メモ
すべてのデコレータ(@Resolver@ResolverField@Args)は@nestjs/graphqlパッケージからエクスポートされます。
これにより、SDLで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()デコレーターは引数としてoptionsオブジェクトを受け取るので、例えば入力タイプの説明を指定することができる。TypeScriptのメタデータ反映システムの制限により、@Fieldデコレーターを使用して手動で型を指定するか、CLIプラグインを使用する必要があることに注意しましょう。
そして、この型をリゾルバクラスで使用できます。
@Mutation(returns => Post)
async upvotePost(
@Args('upvotePostData') upvotePostData: UpvotePostInput,
) {}

スキーマファースト

以前のセクションで使用したAuthorResolverを拡張してみましょう(【Resolver(コードファースト)】を参照)。
@Mutation()
async upvotePost(@Args('postId') postId: number) {
return this.postsService.upvoteById({ id: postId });
}
なお、上記ではビジネスロジックをPostsServiceに移行したものと仮定しました(投稿への問い合わせと、投票数プロパティのインクリメント)。PostsServiceクラス内のロジックは、必要なだけシンプルにすることも、高度にすることもできます。この例の主なポイントは、リゾルバが他のプロバイダとどのように相互作用できるかを示すことです。
最後のステップは既存の型定義に変更した内容を追加することです。
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 {
upvotePost(postId: Int!): Post
}
upvotePost(postId: Int!): PostはアプリケーションのGraphQL APIの一部として呼び出すことができるようになりました。