GraphQL API でサーバーサイドのデータを更新するには、ミューテーション操作 (mutation
) を含むクエリを送信します。
このときどのようなミューテーションを行えるかは、GraphQL スキーマの中で、Mutation
型のフィールドとして定義します。
ミューテーションのスキーマを定義する
次の例では、書籍データを新規作成するための createBook
ミューテーションと、削除するための deleteBook
ミューテーションを定義しています。
フィールド名は変更内容を表す動詞で始めるのが一般的です。
type Mutation {
createBook(title: String!, author: String!): Book!
deleteBook(id: ID!): Boolean!
}
各フィールドにはパラメーター(上記の title
など)を定義することができ、そのパラメーターの指定が必須である場合には、型名の末尾に !
を付けます (String!
)。
ミューテーションが呼び出されたときの実際の処理内容は、GraphQL サーバー側のミューテーション・リゾルバーで実装します。 リゾルバーの実装方法は、各言語の GraphQL サーバーライブラリによって異なります。 例えば、下記は Golang の gqlgen パッケージを使った場合のリゾルバー実装の例です。
// CreateBook is the resolver for the createBook field.
func (r *mutationResolver) CreateBook(
ctx context.Context,
title string,
author *string,
) (*model.Book, error) {
id := uuid.NewString()
book := &model.Book{
ID: id,
Title: title,
Author: author,
}
// 本当はこのあたりで DB などに book を追加
// if err := db.AddBook(book); err != nil {
// return nil, err
// }
return book, nil
}
ミューテーションを実行する
GraphQL API で上記のミューテーションを呼び出すには、次のようなミューテーション操作 (mutation
) を含むドキュメント(クエリ)を送信します。
mutation CreateBook {
createBook(title: "My book", author: "Maku") {
id
title
author
}
}
クエリ操作 (query
) と同様にミューテーション操作 (mutation
) には戻り値があり、通常は次のように、更新後のオブジェクトを示す内容になっています。
この例では、id
フィールドに GraphQL サーバー側で自動生成された UUID が格納されています。
{
"data": {
"createBook": {
"id": "b468b5d5-4446-407b-b11d-eb7cefe438a0",
"title": "My Book",
"author": "Maku"
}
}
}
mutation
ドキュメントには、複数のフィールド(ミューテーション操作)を含むことができます。
mutation CreateBook {
createBook1: createBook(title: "Title1", author: "Author1") {
id
title
author
}
createBook2: createBook(title: "Title2", author: "Author2") {
id
title
author
}
}
複数の query
操作は並列に処理されますが、複数の mutation
操作に関しては上から順番に処理されていくことに注意してください。
いずれかの mutation
操作が失敗すると、その下の mutation
操作は実行されません(すでに実行された mutation
操作がロールバックされることもありません)。
RDB のトランザクション処理のようなことはできないので、1 つの mutation
処理ごとにデータの整合性を保てるよう実装されている必要があります。
(応用)ミューテーションに入力型の変数を使う
フィールドのパラメーターの数が増えてきたときは、入力型 (input type) を定義して、ひとつのオブジェクト型として渡すと分かりやすくなります。 入力型の詳細は下記を参照してください。